diff options
| author | The Miri Conjob Bot <miri@cron.bot> | 2023-11-15 05:12:10 +0000 |
|---|---|---|
| committer | The Miri Conjob Bot <miri@cron.bot> | 2023-11-15 05:12:10 +0000 |
| commit | 34e83402b811b1c4994a68b3f72e60bff04bb076 (patch) | |
| tree | 78ac0a5038cf364e203c7e5719b4b07ff3cb34c5 | |
| parent | 39e142ffd53c81cabfb170c15d9c35b980f7ffd0 (diff) | |
| parent | cc8681b64b6f085bb64c0bbbe6739789d3b1eecf (diff) | |
| download | rust-34e83402b811b1c4994a68b3f72e60bff04bb076.tar.gz rust-34e83402b811b1c4994a68b3f72e60bff04bb076.zip | |
Merge from rustc
1423 files changed, 26069 insertions, 10543 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8cc26d2995e..5f659a1c306 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 @@ -370,6 +373,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 +499,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 +626,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/Cargo.lock b/Cargo.lock index d56d7e3f2b0..d3ecadf6e17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -722,9 +722,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", @@ -1281,26 +1281,15 @@ 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" dependencies = [ @@ -1890,21 +1879,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", @@ -1914,15 +1911,36 @@ dependencies = [ ] [[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 +1949,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.29", ] [[package]] @@ -2055,7 +2073,6 @@ dependencies = [ "anyhow", "clap", "flate2", - "num_cpus", "rayon", "tar", "walkdir", @@ -2215,9 +2232,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 +2327,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" @@ -3005,9 +3022,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" @@ -3181,9 +3198,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 +3208,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]] @@ -3558,6 +3573,7 @@ version = "0.0.0" dependencies = [ "icu_list", "icu_locid", + "icu_locid_transform", "icu_provider", "icu_provider_adapters", "zerovec", @@ -3734,6 +3750,7 @@ dependencies = [ "measureme", "memmap2", "parking_lot 0.12.1", + "portable-atomic", "rustc-hash", "rustc-rayon", "rustc-rayon-core", @@ -4174,7 +4191,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.29", - "synstructure 0.13.0", + "synstructure", ] [[package]] @@ -5218,18 +5235,6 @@ dependencies = [ [[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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" @@ -5497,9 +5502,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", @@ -5923,7 +5928,6 @@ dependencies = [ name = "unwind" version = "0.0.0" dependencies = [ - "cc", "cfg-if", "compiler_builtins", "core", @@ -6296,9 +6300,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 +6362,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 +6374,42 @@ 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.29", + "synstructure", ] [[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.29", + "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 +6418,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.29", ] [[package]] diff --git a/RELEASES.md b/RELEASES.md index 1cc110e6607..a0f6b1203fc 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,120 @@ +Version 1.74.0 (2023-11-16) +========================== + +<a id="1.74.0-Language"></a> + +Language +-------- + +- [Codify that `std::mem::Discriminant<T>` 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) + +<a id="1.74.0-Compiler"></a> + +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/) + +<a id="1.74.0-Libraries"></a> + +Libraries +--------- + +- [Implement `From<OwnedFd/Handle>` for ChildStdin/out/err](https://github.com/rust-lang/rust/pull/98704/) +- [Implement `From<{&,&mut} [T; N]>` for `Vec<T>` 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<char> 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/) + +<a id="1.74.0-Stabilized-APIs"></a> + +Stabilized APIs +--------------- + +- [`core::num::Saturating`](https://doc.rust-lang.org/stable/std/num/struct.Saturating.html) +- [`impl From<io::Stdout> for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStdout%3E-for-Stdio) +- [`impl From<io::Stderr> for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) +- [`impl From<OwnedHandle> for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) +- [`impl From<OwnedFd> for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) +- [`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<char> for u16`](https://doc.rust-lang.org/stable/std/primitive.u16.html#impl-TryFrom%3Cchar%3E-for-u16) +- [`impl<T: Clone, const N: usize> From<&[T; N]> for Vec<T>`](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<T: Clone, const N: usize> From<&mut [T; N]> for Vec<T>`](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<T, const N: usize> 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<T, const N: usize> 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) + +<a id="1.74.0-Cargo"></a> + +Cargo +----- + +- [fix: Set MSRV for internal packages](https://github.com/rust-lang/cargo/pull/12381/) +- [config: merge lists in precedence order](https://github.com/rust-lang/cargo/pull/12515/) +- [fix(update): Clarify meaning of --aggressive as --recursive](https://github.com/rust-lang/cargo/pull/12544/) +- [fix(update): Make `-p` more convenient by being positional](https://github.com/rust-lang/cargo/pull/12545/) +- [feat(help): Add styling to help output ](https://github.com/rust-lang/cargo/pull/12578/) +- [feat(pkgid): Allow incomplete versions when unambigious](https://github.com/rust-lang/cargo/pull/12614/) +- [feat: stabilize credential-process and registry-auth](https://github.com/rust-lang/cargo/pull/12649/) +- [feat(cli): Add '-n' to dry-run](https://github.com/rust-lang/cargo/pull/12660/) +- [Add support for `target.'cfg(..)'.linker`](https://github.com/rust-lang/cargo/pull/12535/) +- [Stabilize `--keep-going`](https://github.com/rust-lang/cargo/pull/12568/) +- [feat: Stabilize lints](https://github.com/rust-lang/cargo/pull/12648/) + +<a id="1.74.0-Rustdoc"></a> + +Rustdoc +------- + +- [Add warning block support in rustdoc](https://github.com/rust-lang/rust/pull/106561/) +- [Accept additional user-defined syntax classes in fenced code blocks](https://github.com/rust-lang/rust/pull/110800/) +- [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/) + +<a id="1.74.0-Compatibility-Notes"></a> + +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<T>` 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<Vec>` leaves the middle type ambiguous, and the new `impl` adds another possibility, so it now requires an explicit type annotation. + +<a id="1.74.0-Internal-Changes"></a> + +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) ========================== diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 9127e1d06e8..996fd5bbecf 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -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); diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 8e7aa59ee34..09a87cf8e2f 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -76,15 +76,14 @@ pub struct ReprOptions { pub align: Option<Align>, pub pack: Option<Align>, 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_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 146a4db200c..c85ff6f5c44 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1548,7 +1548,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, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 0634ee970ec..7c0a78253a2 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -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 @@ -1397,7 +1401,7 @@ pub fn noop_visit_expr<T: MutVisitor>( } ExprKind::Closure(box Closure { binder, - capture_clause: _, + capture_clause, constness, asyncness, movability: _, @@ -1409,6 +1413,7 @@ pub fn noop_visit_expr<T: MutVisitor>( vis.visit_closure_binder(binder); visit_constness(constness, vis); vis.visit_asyncness(asyncness); + vis.visit_capture_by(capture_clause); vis.visit_fn_decl(fn_decl); vis.visit_expr(body); vis.visit_span(fn_decl_span); @@ -1562,6 +1567,15 @@ pub fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) { vis.visit_span(&mut visibility.span); } +pub fn noop_visit_capture_by<T: MutVisitor>(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/token.rs b/compiler/rustc_ast/src/token.rs index 914c97a14ac..a6ee93e8a6b 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -238,9 +238,9 @@ pub enum TokenKind { EqEq, /// `!=` Ne, - /// `>` - Ge, /// `>=` + Ge, + /// `>` Gt, /// `&&` AndAnd, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e091961a144..1caa39e2dd9 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] @@ -857,7 +860,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { } ExprKind::Closure(box Closure { binder, - capture_clause: _, + capture_clause, asyncness: _, constness: _, movability: _, @@ -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) => { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 0fff9a6be92..c07dbbc9d67 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -792,8 +792,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); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c73d2382db8..9a70e6d7c4a 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1201,7 +1201,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let async_expr = this.make_async_expr( - CaptureBy::Value, + CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, closure_id, None, body.span, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a88493acf98..55d50e5fe6a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -443,11 +443,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 }; diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index d22bae816ef..876126b02ea 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 3d0513c8923..ce37f6677cf 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) => { @@ -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; @@ -1212,15 +1207,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> { 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 }); @@ -1328,7 +1326,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 +1394,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 @@ -1552,7 +1537,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 d14b62d6bdc..7f6fcb49317 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_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index e71f421659e..48421ff7140 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -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, } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index e84af12d3f9..edbc3500373 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -673,7 +673,7 @@ 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 => {} } } diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml index fb54937a098..48af4e6f600 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 57f7496dcff..00000000000 --- 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 e4aaf50f5d6..00000000000 --- 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 a485a5af64c..00000000000 --- 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 ce04af868aa..00000000000 --- 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 a13646a0b92..00000000000 --- 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 9023647138b..00000000000 --- 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 647f8f51601..00000000000 --- 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 62957134f07..00000000000 --- 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 4bf244019ff..00000000000 --- 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 84de7cd01a7..00000000000 --- 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 79a97e50f5a..00000000000 --- 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 b976b6cb65a..00000000000 --- 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 d76d567ebf8..00000000000 --- 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 e20941f0c67..00000000000 --- 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 3d8c89f9072..00000000000 --- 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 653ce28d615..00000000000 --- 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 9fa6eb56ade..00000000000 --- 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 66b55c25368..00000000000 --- 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 38da6ecf815..00000000000 --- 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 d4dac1c386e..00000000000 --- 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 931822513cc..00000000000 --- 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 00000000000..bee309f9b81 --- /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 00000000000..1adb58743f7 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs @@ -0,0 +1,40 @@ +// @generated +/// Implement `DataProvider<LocaleFallbackLikelySubtagsV1Marker>` 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 <icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::DataMarker>::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<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker> for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker>, 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(<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::KeyedDataMarker>::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 00000000000..6f8d6590b08 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs @@ -0,0 +1,28 @@ +// @generated +/// Implement `DataProvider<LocaleFallbackParentsV1Marker>` 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 <icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::DataMarker>::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<icu_locid_transform::provider::LocaleFallbackParentsV1Marker> for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::LocaleFallbackParentsV1Marker>, 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(<icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::KeyedDataMarker>::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 00000000000..02eec37ee09 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs @@ -0,0 +1,32 @@ +// @generated +/// Implement `DataProvider<CollationFallbackSupplementV1Marker>` 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 <icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::DataMarker>::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<icu_locid_transform::provider::CollationFallbackSupplementV1Marker> for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::CollationFallbackSupplementV1Marker>, 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(<icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::KeyedDataMarker>::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 00000000000..186f706cdb2 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs @@ -0,0 +1,35 @@ +// @generated +/// Implement `DataProvider<AndListV1Marker>` 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<icu_list::provider::AndListV1Marker> for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_list::provider::AndListV1Marker>, icu_provider::DataError> { + static EN_001: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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: [&<icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::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(<icu_list::provider::AndListV1Marker as icu_provider::KeyedDataMarker>::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 943187808b8..465689f0cb8 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<M>`] 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<DataResponse<::icu_list::provider::AndListV1Marker>, 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<DataResponse<::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker>, 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<DataResponse<::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker>, 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<DataResponse<::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker>, 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<AnyResponse, DataError> { - 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<icu_provider::AnyResponse, icu_provider::DataError> { 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 == <icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == <icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::LocaleFallbackParentsV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == <icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::CollationFallbackSupplementV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == <icu_list::provider::AndListV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_list::provider::AndListV1Marker>::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_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 0b44beeb004..5248a649c34 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 { diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 16814950b0d..8676d2ba7c4 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -273,11 +273,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 +289,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 +300,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; } } diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index 201f0df1238..d0cf339e7ba 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<DefUse> { // 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/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 247200dcd26..9a8f1c97edf 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1022,7 +1022,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 +1114,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 { @@ -2806,7 +2805,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, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 4b95b4783eb..c85b2f0a9d7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -10,7 +10,7 @@ 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_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location, @@ -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 } } @@ -1113,7 +1113,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { && 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) diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 695ac6980cd..41d6b98d7cf 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}; @@ -488,6 +488,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { args_span, } }); + + self.add_note_for_packed_struct_derive(err, original_path.local); } } } @@ -594,4 +596,20 @@ 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/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index d38cfbc54d7..9d6b0a0e91b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -357,7 +357,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ty::BoundRegionKind::BrAnon => None, }, - ty::ReLateBound(..) + ty::ReBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 7b5b52e39b1..ec6d7b74e61 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -253,8 +253,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 { .. } => { @@ -376,8 +376,8 @@ 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 } @@ -422,7 +422,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/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 1a74582389d..5787ea13e79 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -846,7 +846,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)] @@ -1085,18 +1085,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 +1204,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 +1226,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 @@ -1583,7 +1583,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,14 +2142,14 @@ 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() @@ -2173,7 +2173,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 diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 539d0837659..777ebf0d438 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/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 05c2cbd4969..b1f91a05628 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -22,11 +22,10 @@ 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, @@ -2293,19 +2292,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 } diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index ec0131c5349..a31d39e14cd 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/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index d053d0a4b3b..28cc8be8ac9 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, ); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 9f30d9d8ba1..bd01210544f 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -21,7 +21,7 @@ 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}; @@ -751,7 +751,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, @@ -1401,10 +1401,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, ) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index c1f82e19c02..ee0bd13109b 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<Symbol>, + name: Option<Symbol>, ) -> 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 7897a5a63ba..ae7f9c5244c 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -665,7 +665,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 diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 809f9838d20..30c9b35bbac 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/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 92da0c069e5..8c2fa6ee95f 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_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md index 5664cbe7d4f..1a2b2bbc588 100644 --- a/compiler/rustc_codegen_cranelift/Readme.md +++ b/compiler/rustc_codegen_cranelift/Readme.md @@ -76,8 +76,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 1e24d1b113f..10736ff9a55 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -99,6 +99,7 @@ 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::build_bin_and_run("aot.neon", "example/neon.rs", &[]), ]; pub(crate) static RAND_REPO: GitRepo = GitRepo::github( diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt index 7ff805e58d9..2ccdc7d7874 100644 --- a/compiler/rustc_codegen_cranelift/config.txt +++ b/compiler/rustc_codegen_cranelift/config.txt @@ -42,6 +42,7 @@ aot.float-minmax-pass aot.mod_bench aot.issue-72793 aot.issue-59326 +aot.neon testsuite.extended_sysroot test.rust-random/rand diff --git a/compiler/rustc_codegen_cranelift/example/neon.rs b/compiler/rustc_codegen_cranelift/example/neon.rs new file mode 100644 index 00000000000..bad26947967 --- /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/patches/stdlib-lock.toml b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml index 9902bca8eab..8a690bada0d 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 7e3eaacf8ef..b832b06e0ff 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-10" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index a299b6de6b1..cdc78adcf85 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -146,6 +146,11 @@ rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd +# rustc bugs +# ========== +# https://github.com/rust-lang/rust/pull/116447#issuecomment-1790451463 +rm tests/ui/coroutine/gen_block_*.rs + cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist # prevent $(RUSTDOC) from picking up the sysroot built by x.py. It conflicts with the one used by diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 331649b2ec2..ce0eecca8a8 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -13,7 +13,7 @@ use crate::prelude::*; 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<CPlace<'tcx>>, }, Const { @@ -47,7 +47,9 @@ pub(crate) fn codegen_inline_asm<'tcx>( // 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 +57,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 +70,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)), } } @@ -165,7 +168,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( 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 +176,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)); } @@ -726,3 +729,83 @@ fn call_inline_asm<'tcx>( place.write_cvalue(fx, CValue::by_val(value, place.layout())); } } + +pub(crate) fn codegen_xgetbv<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + xcr_no: Value, + ret: CPlace<'tcx>, +) { + // FIXME add .eh_frame unwind info directives + + let operands = vec![ + 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, + }, + ]; + let options = InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM; + + let mut inputs = Vec::new(); + let mut outputs = Vec::new(); + + let mut asm_gen = InlineAssemblyGenerator { + tcx: fx.tcx, + arch: fx.tcx.sess.asm_arch.unwrap(), + enclosing_def_id: fx.instance.def_id(), + template: &[InlineAsmTemplatePiece::String( + " + xgetbv + // out = rdx << 32 | rax + shl rdx, 32 + or rax, rdx + " + .to_string(), + )], + operands: &operands, + options, + registers: Vec::new(), + stack_slots_clobber: Vec::new(), + stack_slots_input: Vec::new(), + stack_slots_output: Vec::new(), + stack_slot_size: Size::from_bytes(0), + }; + asm_gen.allocate_registers(); + asm_gen.allocate_stack_slots(); + + let inline_asm_index = fx.cx.inline_asm_index.get(); + fx.cx.inline_asm_index.set(inline_asm_index + 1); + let asm_name = format!( + "__inline_asm_{}_n{}", + fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"), + inline_asm_index + ); + + let generated_asm = asm_gen.generate_asm_wrapper(&asm_name); + fx.cx.global_asm.push_str(&generated_asm); + + for (i, operand) in operands.iter().enumerate() { + match operand { + CInlineAsmOperand::In { reg: _, value } => { + inputs.push((asm_gen.stack_slots_input[i].unwrap(), *value)); + } + CInlineAsmOperand::Out { reg: _, late: _, place } => { + if let Some(place) = place { + outputs.push((asm_gen.stack_slots_output[i].unwrap(), *place)); + } + } + _ => unreachable!(), + } + } + + call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs); +} diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs index c1694760998..e9b7daf1492 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs @@ -51,6 +51,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 0c211a06dc4..ee098be1fce 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 ea5997a14bb..4c536048626 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs @@ -20,16 +20,21 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( // 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 v = v.load_scalar(fx); + let xcr_no = xcr_no.load_scalar(fx); - // As of writing on XCR0 exists - fx.bcx.ins().trapnz(v, TrapCode::UnreachableCodeReached); + crate::inline_asm::codegen_xgetbv(fx, xcr_no, ret); + } + + "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.sse.cmp.ps" | "llvm.x86.sse2.cmp.pd" => { @@ -177,8 +182,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 +196,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,16 +225,20 @@ 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 { @@ -309,7 +314,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()); @@ -340,7 +347,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 +388,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()); @@ -412,6 +423,369 @@ 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, i64::from(i16::MIN as u16)); + let max_i16 = fx.bcx.ins().iconst(types::I32, i64::from(i16::MAX as u16)); + 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().umin(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().umin(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().umax(lane, min_u16); + let sat = fx.bcx.ins().umin(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().umax(lane, min_u16); + let sat = fx.bcx.ins().umin(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, i64::from(i16::MIN as u16)); + let max_i16 = fx.bcx.ins().iconst(types::I32, i64::from(i16::MAX as u16)); + 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().umin(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().umin(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().umin(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().umin(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.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); + + 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.i64); + assert_eq!(ret_lane_ty, fx.tcx.types.i64); + assert_eq!(lane_count, 2); + assert_eq!(ret_lane_count, 2); + + let imm8 = imm8.load_scalar(fx); + + let control0 = fx.bcx.ins().band_imm(imm8, 0b0000_0001); + let a_lane0 = a.value_lane(fx, 0).load_scalar(fx); + let a_lane1 = a.value_lane(fx, 1).load_scalar(fx); + let temp1 = fx.bcx.ins().select(control0, a_lane1, a_lane0); + + let control4 = fx.bcx.ins().band_imm(imm8, 0b0001_0000); + let b_lane0 = b.value_lane(fx, 0).load_scalar(fx); + let b_lane1 = b.value_lane(fx, 1).load_scalar(fx); + let temp2 = fx.bcx.ins().select(control4, b_lane1, b_lane0); + + fn extract_bit(fx: &mut FunctionCx<'_, '_, '_>, val: Value, bit: i64) -> Value { + let tmp = fx.bcx.ins().ushr_imm(val, bit); + fx.bcx.ins().band_imm(tmp, 1) + } + + let mut res1 = fx.bcx.ins().iconst(types::I64, 0); + for i in 0..=63 { + let x = extract_bit(fx, temp1, 0); + let y = extract_bit(fx, temp2, i); + let mut temp = fx.bcx.ins().band(x, y); + for j in 1..=i { + let x = extract_bit(fx, temp1, j); + let y = extract_bit(fx, temp2, i - j); + let z = fx.bcx.ins().band(x, y); + temp = fx.bcx.ins().bxor(temp, z); + } + let temp = fx.bcx.ins().ishl_imm(temp, i); + res1 = fx.bcx.ins().bor(res1, temp); + } + ret.place_lane(fx, 0).to_ptr().store(fx, res1, MemFlags::trusted()); + + let mut res2 = fx.bcx.ins().iconst(types::I64, 0); + for i in 64..=127 { + let mut temp = fx.bcx.ins().iconst(types::I64, 0); + for j in i - 63..=63 { + let x = extract_bit(fx, temp1, j); + let y = extract_bit(fx, temp2, i - j); + let z = fx.bcx.ins().band(x, y); + temp = fx.bcx.ins().bxor(temp, z); + } + let temp = fx.bcx.ins().ishl_imm(temp, i); + res2 = fx.bcx.ins().bor(res2, temp); + } + ret.place_lane(fx, 1).to_ptr().store(fx, res2, MemFlags::trusted()); + } + + "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 83d5d53624e..bfeeb117ff5 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/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 5f0aa6c5581..21ad2a835fc 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) => { @@ -734,6 +762,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>, diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index a530fc994a2..40373ee1d27 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -384,7 +384,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/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index c0cfe39f1e0..7a86ddc7556 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/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index d5778757caa..0c9f7f19551 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -59,7 +59,7 @@ 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, diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 73821b1685d..307c1264dc1 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -374,15 +374,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { let g = self.get_static(def_id); - // boolean SSA values are i1, but they have to be stored in i8 slots, - // otherwise some LLVM optimization passes don't work as expected - let mut val_llty = self.val_ty(v); - let v = if val_llty == self.type_i1() { - val_llty = self.type_i8(); - llvm::LLVMConstZExt(v, val_llty) - } else { - v - }; + let val_llty = self.val_ty(v); let instance = Instance::mono(self.tcx, def_id); let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 665d195790c..10ca5ad802a 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -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)] diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index a038b3af03d..7fc02a95be0 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -969,7 +969,6 @@ extern "C" { ConstantIndices: *const &'a Value, NumIndices: c_uint, ) -> &'a Value; - pub fn LLVMConstZExt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; 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; diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 7c8ef67ffd1..c86bf81fc13 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; @@ -293,7 +293,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { 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,35 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str }; let feature = backend_feature_name(s)?; - // Warn against use of LLVM specific feature names on the CLI. - if diagnostics && !supported_features.iter().any(|&(v, _)| v == feature) { - let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| { - let llvm_features = to_llvm_features(sess, rust_feature); - if llvm_features.contains(&feature) && !llvm_features.contains(&rust_feature) { - Some(rust_feature) + // Warn against use of LLVM specific feature names and unstable features on the CLI. + if diagnostics { + let feature_state = supported_features.iter().find(|&&(v, _)| v == feature); + if feature_state.is_none() { + let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| { + let llvm_features = to_llvm_features(sess, rust_feature); + if llvm_features.contains(&feature) + && !llvm_features.contains(&rust_feature) + { + Some(rust_feature) + } else { + None + } + }); + let unknown_feature = if let Some(rust_feature) = rust_feature { + UnknownCTargetFeature { + feature, + rust_feature: PossibleFeature::Some { rust_feature }, + } } else { - None - } - }); - let unknown_feature = if let Some(rust_feature) = rust_feature { - UnknownCTargetFeature { - feature, - rust_feature: PossibleFeature::Some { rust_feature }, - } - } else { - UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } - }; - sess.emit_warning(unknown_feature); + UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } + }; + sess.emit_warning(unknown_feature); + } else if feature_state + .is_some_and(|(_name, feature_gate)| !feature_gate.is_stable()) + { + // An unstable feature. Warn about using it. + sess.emit_warning(UnstableCTargetFeature { feature }); + } } if diagnostics { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index bcbb75d9599..dd9d277fb77 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1033,7 +1033,7 @@ 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) { @@ -1070,14 +1070,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, @@ -2370,7 +2362,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. diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 53cc063e55a..ed859cb20de 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -36,7 +36,7 @@ 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, @@ -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(_) @@ -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/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 9c053338c85..d802816bb75 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<Symbol> { + 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<Symbol>)] = &[ +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<Symbol>)] = &[ +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<Symbol>)] = &[ +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<Symbol>)] = &[ +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<Symbol>)] = &[ +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<Symbol>)] = &[ +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<Symbol>)] = &[ +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<Symbol>)] = &[ +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<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))]; +const BPF_ALLOWED_FEATURES: &[(&str, Stability)] = &[("alu32", Unstable(sym::bpf_target_feature))]; -const CSKY_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ +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<Symbol>)] = &[ +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<Symbol>)] = &[ /// 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<Item = (&'static str, Option<Symbol>)> { +pub fn all_known_features() -> impl Iterator<Item = (&'static str, Stability)> { std::iter::empty() .chain(ARM_ALLOWED_FEATURES.iter()) .chain(AARCH64_ALLOWED_FEATURES.iter()) @@ -375,7 +417,7 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol .cloned() } -pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Option<Symbol>)] { +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 ac8123bc1be..35744d9a167 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -104,11 +104,7 @@ pub trait CodegenBackend { outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed>; - /// This is called on the returned `Box<dyn Any>` from `join_codegen` - /// - /// # Panics - /// - /// Panics when the passed `Box<dyn Any>` 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/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index bda6a905503..ed2d81727f7 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -97,11 +97,27 @@ 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. + // (We could allow wide raw pointers where both sides are integers in the future, + // but for now we reject them.) + let Ok(val) = ecx.read_scalar(place) else { + return Err(ValTreeCreationError::Other); + }; + // 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 +238,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 +299,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()), diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index fd173670374..d9f583c1d1f 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/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 135c99fefbc..76116e33985 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -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,7 +500,7 @@ 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::<HasMutInterior, _>( &self.ccx, 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 a137f84b738..a23922c778f 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 05902976638..32af537e271 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -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); } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 4d71f763667..5922922d47b 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -848,11 +848,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 2701fdbbd77..8d91c4c4376 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -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/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 5d7f385c6e4..d09c026c4b4 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -127,6 +127,9 @@ impl<F: FnOnce()> Drop for OnDrop<F> { } } +/// 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<F> { diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index a8c442377fb..266e54604a6 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 29516fffd6a..639f05c9e52 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -79,7 +79,7 @@ impl<T> Sharded<T> { pub fn lock_shard_by_value<K: Hash + ?Sized>(&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<T> Sharded<T> { 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<T> Sharded<T> { } #[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 f957734b04d..43221d70e21 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 339aebbf81a..040a8aa6b63 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<T>, 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 39dddb59569..7783de57fba 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<Option<Box<dyn Any + Send + 'static>>>, + panic: Mutex<Option<IntoDynSyncSend<Box<dyn Any + Send + 'static>>>>, } impl ParallelGuard { pub fn run<R>(&self, f: impl FnOnce() -> R) -> Option<R> { catch_unwind(AssertUnwindSafe(f)) .map_err(|err| { - *self.panic.lock() = Some(err); + let mut panic = self.panic.lock(); + if panic.is_none() || !(*err).is::<FatalErrorMarker>() { + *panic = Some(IntoDynSyncSend(err)); + } }) .ok() } @@ -37,7 +42,7 @@ impl ParallelGuard { pub fn parallel_guard<R>(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 @@ -77,12 +82,12 @@ mod disabled { }) } - pub fn try_par_for_each_in<T: IntoIterator, E: Copy>( + pub fn try_par_for_each_in<T: IntoIterator, E>( t: T, mut for_each: impl FnMut(T::Item) -> Result<(), E>, ) -> Result<(), E> { parallel_guard(|guard| { - t.into_iter().fold(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret)) + t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and) }) } @@ -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) } @@ -178,7 +191,7 @@ mod enabled { pub fn try_par_for_each_in< T: IntoIterator + IntoParallelIterator<Item = <T as IntoIterator>::Item>, - E: Copy + Send, + E: Send, >( t: T, for_each: impl Fn(<T as IntoIterator>::Item) -> Result<(), E> + DynSync + DynSend, @@ -187,11 +200,10 @@ mod enabled { if mode::is_dyn_thread_safe() { let for_each = FromDyn::from(for_each); t.into_par_iter() - .fold_with(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret)) - .reduce(|| Ok(()), |a, b| a.and(b)) + .filter_map(|i| guard.run(|| for_each(i))) + .reduce(|| Ok(()), Result::and) } else { - t.into_iter() - .fold(Ok(()), |ret, i| guard.run(|| for_each(i)).unwrap_or(ret).and(ret)) + t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and) } }) } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index ee4337754a9..7905a0e3924 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -41,6 +41,7 @@ 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; @@ -421,8 +422,12 @@ fn run_compiler( // effects of writing the dep-info and reporting errors. queries.global_ctxt()?.enter(|tcx| tcx.output_filenames(())); } 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(); @@ -477,8 +482,7 @@ fn run_compiler( } if sess.opts.unstable_opts.print_vtable_sizes { - let crate_name = - compiler.session().opts.crate_name.as_deref().unwrap_or("<UNKNOWN_CRATE>"); + let crate_name = queries.global_ctxt()?.enter(|tcx| tcx.crate_name(LOCAL_CRATE)); sess.code_stats.print_vtable_sizes(crate_name); } @@ -492,10 +496,6 @@ fn run_compiler( linker.link()? } - if sess.opts.unstable_opts.perf_stats { - sess.print_perf_stats(); - } - if sess.opts.unstable_opts.print_fuel.is_some() { eprintln!( "Fuel used by {}: {}", diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 8c6fee83013..cc533b9941a 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -217,7 +217,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> }, } diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md index 8b4b2dc87fd..20f51441c29 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<u8>, Some); ``` @@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option<u8>` 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<u8>, Some.0); ``` diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 6d95fbcfad0..68dba860291 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -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/lib.rs b/compiler/rustc_errors/src/lib.rs index dd462cc6486..8ae95cbeed2 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -10,7 +10,6 @@ #![feature(if_let_guard)] #![feature(let_chains)] #![feature(never_type)] -#![feature(result_option_inspect)] #![feature(rustc_attrs)] #![feature(yeet_expr)] #![feature(try_blocks)] diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs index d3a08da6283..67e4963fddf 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_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 11782e33d84..64b5a7d2921 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -526,6 +526,8 @@ 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, "CURRENT_RUSTC_VERSION", 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`. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d88f165b9e5..c4e44a6a4e3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3566,6 +3566,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, _), .. }) diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 3e700f2da86..cb9259998e3 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -350,7 +350,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 { diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 2fcb45ef8aa..5a9c67a6a9d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -250,7 +250,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)) => { @@ -1622,7 +1622,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r } + // FIXME(@lcnr): This is broken, erasing bound regions + // impacts selection as it results in different types. + if r.is_bound() { self.tcx.lifetimes.re_erased } else { r } } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { @@ -2845,6 +2847,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 +2856,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); 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 90babbb63a0..d3a383ff7c5 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2162,7 +2162,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 +2217,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 <https://github.com/rust-lang/rust/pull/117542#issue-1976337685>. + 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 +2345,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/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index c61719c1fd2..eb009b9368f 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 }, @@ -411,7 +411,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 +465,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/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 046983e90f7..729e9f2f1d1 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}; @@ -762,7 +763,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> 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) => { @@ -1877,7 +1878,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/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 7eeb7837467..8d87cb57b90 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -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().delay_span_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), 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 6424d1c7931..d51e9eb5983 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -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 { diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index ca7679cfba0..d5fb4340e1c 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -196,6 +196,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseAllBoundRegions<'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 } + // FIXME(@lcnr): only erase escaping bound regions! + if r.is_bound() { self.tcx.lifetimes.re_erased } else { r } } } diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs index a6410c944f7..85703c60c30 100644 --- a/compiler/rustc_hir_analysis/src/outlives/utils.rs +++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs @@ -167,8 +167,8 @@ 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, diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 5f8b1ace68b..6c1efb6470e 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -419,9 +419,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { 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(_) => {} diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 1ce6bb6ca15..5f82d9f06c6 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2017,7 +2017,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 => {} } } diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index b8a265d4971..1edc3efbc77 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -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 a70ead8e57d..7807ff6547d 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}; @@ -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()); diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index acaa3e02f09..77d6183f862 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -34,6 +34,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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 +50,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( diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a11fe10c01c..a6f78dc8ab5 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, @@ -512,7 +512,7 @@ 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); @@ -564,7 +564,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 +582,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); @@ -959,12 +959,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... @@ -1305,7 +1332,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, ) { @@ -1524,21 +1551,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); } } @@ -2829,7 +2877,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 } @@ -2988,16 +3036,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .ok() } - fn point_at_index_if_possible( - &self, - errors: &mut Vec<traits::FulfillmentError<'tcx>>, - span: Span, - ) { + fn point_at_index(&self, errors: &mut Vec<traits::FulfillmentError<'tcx>>, 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; @@ -3119,6 +3179,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (ident, _def_scope) = self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block); + 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 { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index b5a07f0d3e9..750ed2c3491 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -797,6 +797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { qpath: &'tcx QPath<'tcx>, hir_id: hir::HirId, span: Span, + args: Option<&'tcx [hir::Expr<'tcx>]>, ) -> (Res, Option<RawTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]) { debug!( "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}", @@ -898,7 +899,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 ) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index e93d180fc13..a1ce5983f30 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -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 c43d4932fb9..2e0ab1560f4 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2326,14 +2326,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 +2353,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()), diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 86a0e95de1d..d69d2529b18 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; diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 74f469cb39c..a51fa8354c9 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -801,7 +801,7 @@ 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() { + if new_trait_ref.has_non_region_bound_vars() { this.tcx.sess.delay_span_bug( this.span, "tried to select method from HRTB with non-lifetime bound vars", @@ -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, ); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 12cc5ed2f1a..bd40e6c1047 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -34,7 +34,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 +50,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 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name: Ident, source: SelfSource<'tcx>, error: MethodError<'tcx>, - args: Option<MethodCallComponents<'tcx>>, + args: Option<&'tcx [hir::Expr<'tcx>]>, expected: Expectation<'tcx>, trait_missing_method: bool, ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> { @@ -167,6 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_candidates_on_method_error( rcvr_ty, item_name, + source, args, span, &mut err, @@ -266,23 +258,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 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty: Ty<'tcx>, item_name: Ident, source: SelfSource<'tcx>, - args: Option<MethodCallComponents<'tcx>>, + args: Option<&'tcx [hir::Expr<'tcx>]>, sugg_span: Span, no_match_data: &mut NoMatchData<'tcx>, expected: Expectation<'tcx>, @@ -377,23 +369,25 @@ 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) - } else { - tcx.sess.create_err(NoAssociatedItem { - span, - item_kind, - item_name, - ty_prefix: if trait_missing_method { - // FIXME(mu001999) E0599 maybe not suitable here because it is for types - Cow::from("trait") - } else { - rcvr_ty.prefix_string(self.tcx) - }, - ty_str: ty_str_reported, - trait_missing_method, - }) - }; + 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, + item_kind, + item_name, + ty_prefix: if trait_missing_method { + // FIXME(mu001999) E0599 maybe not suitable here because it is for types + Cow::from("trait") + } else { + rcvr_ty.prefix_string(self.tcx) + }, + ty_str: ty_str_reported, + trait_missing_method, + }) + }; if tcx.sess.source_map().is_multiline(sugg_span) { err.span_label(sugg_span.with_hi(span.lo()), ""); } @@ -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,7 +481,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); probe.is_ok() }); - self.note_internal_mutation_in_method( &mut err, rcvr_expr, @@ -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, @@ -975,7 +974,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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,7 +1167,7 @@ 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, @@ -1240,7 +1239,40 @@ 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 +1281,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, rcvr_ty: Ty<'tcx>, item_name: Ident, - args: Option<MethodCallComponents<'tcx>>, + self_source: SelfSource<'tcx>, + args: Option<&'tcx [hir::Expr<'tcx>]>, span: Span, err: &mut Diagnostic, sources: &mut Vec<CandidateSource>, @@ -1319,38 +1352,21 @@ 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,24 +1388,23 @@ 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); } } } @@ -1407,6 +1422,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<Self>` or `Result<Self, _>`. + 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<Self>` or `Result<Self, _>`. + let ret_ty = self.tcx.fn_sig(item.def_id).skip_binder().output(); + let ret_ty = self.tcx.erase_late_bound_regions(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<Self>` or `-> Result<Self, _>` + 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::<Vec<_>>(); + 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::<Vec<Span>>() + .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::<Vec<String>>() + .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 +1510,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>, item_name: Ident, - args: Option<MethodCallComponents<'tcx>>, + args: Option<&'tcx [hir::Expr<'tcx>]>, sugg_span: Span, ) { let mut has_unsuggestable_args = false; @@ -1490,38 +1584,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None }; let mut applicability = Applicability::MachineApplicable; - let args = if let Some(MethodCallComponents { receiver, 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::<Vec<_>>() + 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::<Vec<_>>() + } else { + // There is no `Self` kind to infer the arguments from + if has_unsuggestable_args { + applicability = Applicability::HasPlaceholders; + } + args.iter().collect() + }; + format!( + "({}{})", + first_arg.unwrap_or(""), + explicit_args + .iter() + .map(|arg| self + .tcx + .sess + .source_map() + .span_to_snippet(arg.span) + .unwrap_or_else(|_| { + applicability = Applicability::HasPlaceholders; + "_".to_owned() + })) + .collect::<Vec<_>>() + .join(", "), + ) } else { - // There is no `Self` kind to infer the arguments from - if has_unsuggestable_args { - applicability = Applicability::HasPlaceholders; - } - args.iter().collect() + applicability = Applicability::HasPlaceholders; + "(...)".to_owned() }; - format!( - "({}{})", - first_arg.unwrap_or(""), - explicit_args - .iter() - .map(|arg| self - .tcx - .sess - .source_map() - .span_to_snippet(arg.span) - .unwrap_or_else(|_| { - applicability = Applicability::HasPlaceholders; - "_".to_owned() - })) - .collect::<Vec<_>>() - .join(", "), - ) - } else { - applicability = Applicability::HasPlaceholders; - "(...)".to_owned() - }; err.span_suggestion( sugg_span, "use associated function syntax instead", @@ -3179,56 +3275,59 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> { } fn print_disambiguation_help<'tcx>( - item_name: Ident, - args: Option<MethodCallComponents<'tcx>>, + tcx: TyCtxt<'tcx>, err: &mut Diagnostic, - trait_name: String, - rcvr_ty: Ty<'_>, - impl_self_ty: Option<Ty<'_>>, - 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<usize>, span: Span, - candidate: Option<usize>, - source_map: &source_map::SourceMap, - fn_has_self_parameter: bool, + item: ty::AssocItem, ) -> Option<String> { + 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()[0] + .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::<Vec<_>>() .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 d0d3b0e5b73..f40406c6726 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -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>| { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 50684482c0d..b30f9b82fbb 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)); @@ -1060,7 +1060,7 @@ 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"); self.set_tainted_by_errors(e); diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 75c70ec59fb..17b81acd506 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -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), }; @@ -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 896aacc6993..2dfe7272673 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -784,7 +784,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEarlyRegions<'tcx> { } } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if r.is_late_bound() { r } else { self.tcx.lifetimes.re_erased } + if r.is_bound() { r } else { self.tcx.lifetimes.re_erased } } } @@ -822,7 +822,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> 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 5d885e07192..e74173b24a9 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/errors.rs b/compiler/rustc_incremental/src/errors.rs index 05ed4f7598d..61bb0353a9f 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -271,12 +271,6 @@ pub struct LoadDepGraph { } #[derive(Diagnostic)] -#[diag(incremental_decode_incr_cache)] -pub struct DecodeIncrCache { - pub err: String, -} - -#[derive(Diagnostic)] #[diag(incremental_write_dep_graph)] pub struct WriteDepGraph<'a> { pub path: &'a Path, diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index cbd55fe4205..6dfc4096910 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -30,8 +30,6 @@ pub enum LoadResult<T> { DataOutOfDate, /// Loading the dep graph failed. LoadDepGraph(PathBuf, std::io::Error), - /// Decoding loaded incremental cache failed. - DecodeIncrCache(Box<dyn std::any::Any + Send>), } impl<T: Default> LoadResult<T> { @@ -44,9 +42,7 @@ impl<T: Default> LoadResult<T> { } ( Some(IncrementalStateAssertion::Loaded), - LoadResult::LoadDepGraph(..) - | LoadResult::DecodeIncrCache(..) - | LoadResult::DataOutOfDate, + LoadResult::LoadDepGraph(..) | LoadResult::DataOutOfDate, ) => { sess.emit_fatal(errors::AssertLoaded); } @@ -58,10 +54,6 @@ impl<T: Default> LoadResult<T> { 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 }); @@ -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_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index ece61ff1252..d0b4889b45f 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -237,23 +237,12 @@ impl<T: Idx> BitSet<T> { 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<T> { - // 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<R: Idx, C: Idx> BitMatrix<R, C> { pub fn from_row_n(row: &BitSet<C>, num_rows: usize) -> BitMatrix<R, C> { 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<R: Idx, C: Idx> BitMatrix<R, C> { 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<u32> { } } -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> { - self.checked_shl(rhs) - } - - fn checked_shr(self, rhs: u32) -> Option<Self> { - self.checked_shr(rhs) - } -} - -impl std::fmt::Debug for FiniteBitSet<u64> { - 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> { - self.checked_shl(rhs) - } - - fn checked_shr(self, rhs: u32) -> Option<Self> { - self.checked_shr(rhs) - } -} - -impl std::fmt::Debug for FiniteBitSet<u128> { - 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/vec.rs b/compiler/rustc_index/src/vec.rs index 99e72e49f8e..66c5cc774b2 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -137,10 +137,6 @@ impl<I: Idx, T> IndexVec<I, T> { self.raw.truncate(a) } - pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> { - 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 cb0f0db220d..7e5e41bd2d1 100644 --- a/compiler/rustc_index/src/vec/tests.rs +++ b/compiler/rustc_index/src/vec/tests.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] - // Allows the macro invocation below to work use crate as rustc_index; diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 57bc14ebcb3..869878420ae 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -73,8 +73,11 @@ impl<'a> DescriptionCtx<'a> { // ReFree 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 `ReBound` 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/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 0e2f9ba70fe..ba7007d908f 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -13,7 +13,6 @@ 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 +42,6 @@ impl<'tcx> InferCtxt<'tcx> { where V: TypeFoldable<TyCtxt<'tcx>>, { - self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed); - Canonicalizer::canonicalize(value, self, self.tcx, &CanonicalizeAllFreeRegions, query_state) } @@ -62,8 +59,6 @@ impl<'tcx> InferCtxt<'tcx> { where V: TypeFoldable<TyCtxt<'tcx>>, { - self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed); - Canonicalizer::canonicalize( value, self, @@ -138,8 +133,6 @@ impl<'tcx> InferCtxt<'tcx> { where V: TypeFoldable<TyCtxt<'tcx>>, { - self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed); - Canonicalizer::canonicalize( value, self, @@ -232,7 +225,7 @@ impl CanonicalizeMode for CanonicalizeUserTypeAnnotation { match *r { ty::ReEarlyBound(_) | ty::ReFree(_) | 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 +336,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> 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 { @@ -776,7 +769,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 ed101082130..d911e28484c 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. diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e4be435fded..f09a33be839 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -175,10 +175,10 @@ pub(super) fn note_and_explain_region<'tcx>( 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); @@ -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 { @@ -2444,18 +2444,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 @@ -2764,13 +2768,13 @@ 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 diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index fe18d00293a..f0b33d30e2c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -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 diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 35204478c54..e212547eaaf 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -110,7 +110,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> 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 } diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs index 17fe3aa7b44..84891022720 100644 --- a/compiler/rustc_infer/src/infer/generalize.rs +++ b/compiler/rustc_infer/src/infer/generalize.rs @@ -327,7 +327,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); } 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 bee0a978ad0..4ff9d749422 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::{ReBound, RePlaceholder, ReVar}; use rustc_middle::ty::{ReEarlyBound, ReErased, ReError, ReFree, ReStatic}; -use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar}; 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); } @@ -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); } @@ -478,7 +478,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); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 4ee897ffe98..3c539f18eb9 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::*; @@ -472,9 +472,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, @@ -510,9 +510,9 @@ pub enum RegionVariableOrigin { /// Region variables created as the values for early-bound regions. EarlyBoundRegion(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), @@ -1456,13 +1456,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<T>( &self, span: Span, - lbrct: LateBoundRegionConversionTime, + lbrct: BoundRegionConversionTime, value: ty::Binder<'tcx, T>, ) -> T where @@ -1475,7 +1475,7 @@ impl<'tcx> InferCtxt<'tcx> { struct ToFreshVars<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, span: Span, - lbrct: LateBoundRegionConversionTime, + lbrct: BoundRegionConversionTime, map: FxHashMap<ty::BoundVar, ty::GenericArg<'tcx>>, } @@ -1485,7 +1485,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() @@ -2042,7 +2042,7 @@ impl RegionVariableOrigin { | Autoref(a) | Coercion(a) | EarlyBoundRegion(a, ..) - | LateBoundRegion(a, ..) + | BoundRegion(a, ..) | UpvarRegion(_, a) => a, Nll(..) => bug!("NLL variable used with `span`"), } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 7a5dec22fe0..7a792d30cc7 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -432,7 +432,7 @@ where fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { match *r { // ignore bound regions, keep visiting - ty::ReLateBound(_, _) => ControlFlow::Continue(()), + ty::ReBound(_, _) => ControlFlow::Continue(()), _ => { (self.op)(r); ControlFlow::Continue(()) diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 38819e8ad8a..f867876a2e6 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -213,8 +213,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 +241,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/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index 398ac94ee36..2db8579af52 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<Self::BreakTy> { match *r { // ignore bound regions, keep visiting - ty::ReLateBound(_, _) => ControlFlow::Continue(()), + ty::ReBound(_, _) => ControlFlow::Continue(()), _ => { (self.op)(r); ControlFlow::Continue(()) 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 6f973ee37f5..959b34aa145 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/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 3fa9a7333a4..de142f05fb7 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; @@ -531,7 +531,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) => { @@ -667,7 +667,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { | 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), } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 3c566e0dd6d..8cee13ce4ec 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -340,7 +340,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 +351,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( diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 8e66083a390..8a5851bd5cb 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -4,11 +4,11 @@ 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, + 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; @@ -679,7 +679,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 +690,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 +746,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); diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index d44691b5e9b..82483ac7dc0 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_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 918e484b9f4..bef9f469cc6 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2217,15 +2217,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, diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index fe13162cd4a..ed1e8771323 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -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 3f2bf2c9b44..142384e6d0c 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -25,7 +25,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) || \ diff --git a/compiler/rustc_macros/src/current_version.rs b/compiler/rustc_macros/src/current_version.rs index 5e3b91c17bf..42ca60a6d8a 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<Self> { - let paren; - input.parse::<kw::env>()?; - input.parse::<Token![!]>()?; - 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<Self, Box<dyn std::error::Error>> { - let value = proc_macro::tracked_env::var(env_var.value())?; + fn parse_cfg_release(env_var: &str) -> Result<Self, Box<dyn std::error::Error>> { + 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 1a8174bfd96..31ad9cdb216 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 e9a5cd9de97..2755a161d91 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<Path>, + /// 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 877271ff077..0f9e68cdc50 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<TokenStream, DiagnosticDeriveError> { + pub(crate) fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> { 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 12563292181..2700f02e33a 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<u32> = RefCell::new(0); + pub(crate) static CODE_IDENT_COUNT: RefCell<u32> = 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 75a2f7009c2..6d23b9ac99d 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -38,33 +38,16 @@ fn parse_attributes(field: &syn::Field) -> Attributes { attrs } -pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(crate) 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); - } - } - }); - 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"), - }; + let discriminant = hash_stable_discriminant(&mut s); + let body = hash_stable_body(&mut s); s.bound_impl( quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>), @@ -81,32 +64,13 @@ pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_ma ) } -pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { +pub(crate) 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| { - 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); - } - } - }); - 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"), - }; + let discriminant = hash_stable_discriminant(&mut s); + let body = hash_stable_body(&mut s); s.bound_impl( quote!( @@ -126,3 +90,30 @@ pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::To }, ) } + +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! {} + } else if let Some(project) = attrs.project { + quote! { + (&#bi.#project).hash_stable(__hcx, __hasher); + } + } else { + quote! { + #bi.hash_stable(__hcx, __hasher); + } + } + }) +} diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 193dbd75fbd..a6666636032 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -26,6 +26,9 @@ 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) diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index ba75517d7a6..047066ac681 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<I = ::rustc_middle::ty::TyCtxt<'tcx>>}); - s.add_bounds(synstructure::AddBounds::Generics); + let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> } + } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") { + quote! { <I = I> } + } 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! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> } + } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") { + quote! { <I = I> } + } else { + quote! {} + }; + let encoder_ty = quote! { __E }; - s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_type_ir::codec::TyEncoder<I = ::rustc_middle::ty::TyCtxt<'tcx>>}); - 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 4129712a6b2..3de4a904e5f 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}; @@ -318,13 +320,4 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) { }; (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/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index ec2517b581e..b06b4fb87cd 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -8,6 +8,7 @@ #![cfg_attr(not(bootstrap), feature(coroutines))] #![feature(iter_from_coroutine)] #![feature(let_chains)] +#![feature(if_let_guard)] #![feature(proc_macro_internals)] #![feature(macro_metavar_expr)] #![feature(min_specialization)] diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index de436c16ca9..2042863d189 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2386,31 +2386,32 @@ 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_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 0b5426c3bb1..5a957d2c26d 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -63,7 +63,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 +79,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; @@ -222,7 +222,7 @@ pub enum CanonicalVarKind<'tcx> { Effect, /// A "placeholder" that represents "any const". - PlaceholderConst(ty::PlaceholderConst<'tcx>, Ty<'tcx>), + PlaceholderConst(ty::PlaceholderConst, Ty<'tcx>), } impl<'tcx> CanonicalVarKind<'tcx> { @@ -389,7 +389,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 041a63776d1..92d1fcc7ed2 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -58,8 +58,7 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> { // 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() { @@ -69,7 +68,7 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { | ty::ReEarlyBound(..) | 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 448a3029ae9..fd29e74e905 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -59,7 +59,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)] diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7054cede2d8..874c997c23b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1611,14 +1611,29 @@ impl Location { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum DefLocation { Argument, - Body(Location), + Assignment(Location), + CallReturn { call: BasicBlock, target: Option<BasicBlock> }, } impl DefLocation { pub fn dominates(self, location: Location, dominators: &Dominators<BasicBlock>) -> 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 debd85dad2e..a1324858416 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 ", }; diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 0540eb0efd6..d609965f36f 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -416,7 +416,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 +430,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/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 5864acaed7b..3471d620ee6 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -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 b6543affc6d..7b0f27f9b34 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 }, diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 931ee7fd05e..6ab2da23a8a 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -278,7 +278,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/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 0f0ca3a1420..d47cfd5712f 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 e20e9d9312c..cdde6a596a8 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<T: Copy> { @@ -29,8 +30,15 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> { }; Erased::<<T as EraseType>::Result> { + // `transmute_unchecked` is needed here because it does not have `transmute`'s size check + // (and thus allows to transmute between `T` and `MaybeUninit<T::Result>`) (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::<T, MaybeUninit<T::Result>>(src) }, } } @@ -38,22 +46,24 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> { #[inline(always)] pub fn restore<T: EraseType>(value: Erase<T>) -> T { let value: Erased<<T as EraseType>::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::<MaybeUninit<T::Result>, T>(value.data) } } impl<T> EraseType for &'_ T { - type Result = [u8; size_of::<*const ()>()]; + type Result = [u8; size_of::<&'static ()>()]; } impl<T> EraseType for &'_ [T] { - type Result = [u8; size_of::<*const [()]>()]; + type Result = [u8; size_of::<&'static [()]>()]; } impl<T> EraseType for &'_ ty::List<T> { - type Result = [u8; size_of::<*const ()>()]; + type Result = [u8; size_of::<&'static ty::List<()>>()]; } impl<I: rustc_index::Idx, T> EraseType for &'_ rustc_index::IndexSlice<I, T> { diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index d03d92c3a4b..8feefb4c03c 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, .. } => { diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 9e2ff3820af..6cd75e08727 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -305,9 +305,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. @@ -455,6 +460,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 diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index cfacccd2679..af5ffc20d48 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -84,7 +84,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) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 68812bba42f..1598d05251d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -106,7 +106,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { 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>; @@ -327,7 +327,7 @@ pub struct CommonLifetimes<'tcx> { pub re_vars: Vec<Region<'tcx>>, /// 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<Vec<Region<'tcx>>>, } @@ -402,7 +402,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 }, )) diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 77a50fa9276..0094825fc70 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 7895993ccff..cfd36fd8c7c 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<TyCtxt<'tcx>>, { - // 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<TyCtxt<'tcx>> 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 738bb5e8b19..b26f98769c1 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)] diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 75ea53195a3..f95ceeff150 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 a348e9f608a..4d7b12662c6 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -34,26 +34,6 @@ impl FlagComputation { result.flags } - pub fn bound_var_flags(vars: &ty::List<ty::BoundVariableKind>) -> 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 - } - fn add_flags(&mut self, flags: TypeFlags) { self.flags = self.flags | flags; } @@ -77,7 +57,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 +137,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(..) => { @@ -310,7 +294,7 @@ 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); } } @@ -333,7 +317,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 00529a1e066..e8ff3b230cb 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<TyCtxt<'tcx>> 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 } @@ -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 }, @@ -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<TyCtxt<'tcx>> 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 41a1bf04e5f..c9607b2245a 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -843,7 +843,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> { None => region_param_out_of_range(data, self.args), } } - ty::ReLateBound(..) + ty::ReBound(..) | ty::ReFree(_) | ty::ReStatic | ty::RePlaceholder(_) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 4223e503f5e..aca6acd783b 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"), } } @@ -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(_), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 739d4fa886e..e1c616ba078 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1527,7 +1527,7 @@ pub struct BoundConst<'tcx> { pub ty: Ty<'tcx>, } -pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>; +pub type PlaceholderConst = Placeholder<BoundVar>; /// When type checking, we use the `ParamEnv` to track /// details about the set of where-clauses that are in scope at this @@ -2011,7 +2011,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 diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 8d895732dff..cabf2ab5dfe 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<TyCtxt<'tcx>> 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. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index baf160bcc99..21bf5b4b3b1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2160,7 +2160,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { match *region { ty::ReEarlyBound(ref data) => data.has_name(), - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: br, .. }, .. @@ -2234,7 +2234,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { return Ok(()); } } - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: br, .. }, .. @@ -2315,7 +2315,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> 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 +2338,9 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> 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 } @@ -2450,7 +2450,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { 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 }, @@ -2466,7 +2466,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { 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 +2480,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 +2496,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, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 44592b10d55..d0df4498a66 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1476,7 +1476,7 @@ impl<'tcx> Region<'tcx> { } #[inline] - pub fn new_late_bound( + pub fn new_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, bound_region: ty::BoundRegion, @@ -1488,7 +1488,7 @@ impl<'tcx> Region<'tcx> { { re } else { - tcx.intern_region(ty::ReLateBound(debruijn, bound_region)) + tcx.intern_region(ty::ReBound(debruijn, bound_region)) } } @@ -1550,7 +1550,7 @@ impl<'tcx> Region<'tcx> { 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::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region), ty::ReFree(ty::FreeRegion { scope, bound_region }) => { Region::new_free(tcx, scope, bound_region) } @@ -1723,7 +1723,7 @@ impl<'tcx> Region<'tcx> { if self.has_name() { match *self { ty::ReEarlyBound(ebr) => Some(ebr.name), - ty::ReLateBound(_, br) => br.kind.get_name(), + ty::ReBound(_, br) => br.kind.get_name(), ty::ReFree(fr) => fr.bound_region.get_name(), ty::ReStatic => Some(kw::StaticLifetime), ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(), @@ -1745,7 +1745,7 @@ impl<'tcx> Region<'tcx> { pub fn has_name(self) -> bool { match *self { ty::ReEarlyBound(ebr) => ebr.has_name(), - ty::ReLateBound(_, br) => br.kind.is_named(), + ty::ReBound(_, br) => br.kind.is_named(), ty::ReFree(fr) => fr.bound_region.is_named(), ty::ReStatic => true, ty::ReVar(..) => false, @@ -1771,8 +1771,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 +1783,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, } } @@ -1814,8 +1814,8 @@ impl<'tcx> Region<'tcx> { 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; diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index e9240d1b268..1a76a8d350d 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -638,7 +638,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 a251518d145..144e98f784a 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -468,7 +468,7 @@ 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::Bound, ty::ReBound(di, reg)) => { if !seen_late.insert((di, reg)) { return Err(NotUniqueParam::DuplicateParam(lt.into())); } diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index ab0999b3f19..f14232d3435 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -111,16 +111,16 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> { } /// 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<Self::BreakTy> { 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<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { 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); } @@ -494,15 +494,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor { &mut self, t: &Binder<'tcx, T>, ) -> ControlFlow<Self::BreakTy> { - // 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) @@ -617,7 +613,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - 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/values.rs b/compiler/rustc_middle/src/values.rs index f30993c9a69..2b4ae373626 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -114,12 +114,11 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>> } impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>> { - 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)))) } } diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 32711c23dc4..7dd0e7d4b92 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -221,6 +221,11 @@ mir_build_non_exhaustive_omitted_pattern = some variants are not matched explici .help = ensure that all variants are matched explicitly by adding the suggested match arms .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found +mir_build_non_exhaustive_omitted_pattern_lint_on_arm = the lint level must be set on the whole match + .help = it no longer has any effect to set the lint level on an individual match arm + .label = remove this attribute + .suggestion = set the lint level on the whole match + mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty .def_note = `{$peeled_ty}` defined here .type_note = the matched value is of type `{$ty}` @@ -242,7 +247,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 @@ -315,6 +320,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 = @@ -381,3 +387,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/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 3de2f45ad9a..d302d538ad4 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -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<T> = Result<T, ParseError>; diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index e2ab2cb90c7..a6f9caada2d 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<Item = StmtId>) -> 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<Item = StmtId>) -> 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<BasicBlockData<'tcx>> { + fn parse_block_def(&self, expr_id: ExprId, is_cleanup: bool) -> PResult<BasicBlockData<'tcx>> { 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 fd2c57a0a6f..4ce7f831c87 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<StatementKind<'tcx>> { 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<TerminatorKind<'tcx>> { 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<UnwindTerminateReason> { + 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<UnwindAction> { + 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<SwitchTargets> { 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<Rvalue<'tcx>> { 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<Operand<'tcx>> { 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_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index c6a09f6568a..7e9191a37d3 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -690,7 +690,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { 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/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index a43aae6f449..304870274ac 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -2021,7 +2021,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/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 58d6be50b90..886d805454d 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -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.hir().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) } - 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) + } + DefKind::Coroutine => { + 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)) + } + 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 } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 45be5015371..fcb56360782 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -35,6 +35,10 @@ struct UnsafetyVisitor<'a, 'tcx> { param_env: ParamEnv<'tcx>, inside_adt: bool, warnings: &'a mut Vec<UnusedUnsafeWarning>, + + /// 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 +99,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( @@ -278,7 +288,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 +307,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); @@ -394,7 +405,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } 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) { @@ -470,7 +483,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 +491,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); @@ -543,7 +548,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().map_or(false, |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,61 +574,89 @@ 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( UNSAFE_OP_IN_UNSAFE_FN, @@ -617,6 +665,7 @@ impl UnsafeOpKind { UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { span, function: &with_no_trimmed_paths!(tcx.def_path_str(*did)), + unsafe_not_inherited_note, }, ), } @@ -831,6 +880,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 5bfce3ab510..418f9bb9de9 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -29,6 +29,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, } #[derive(LintDiagnostic)] @@ -37,6 +39,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, } #[derive(LintDiagnostic)] @@ -45,6 +49,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, } #[derive(LintDiagnostic)] @@ -53,6 +59,8 @@ pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, } #[derive(LintDiagnostic)] @@ -61,6 +69,8 @@ pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, } #[derive(LintDiagnostic)] @@ -69,6 +79,8 @@ pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, } #[derive(LintDiagnostic)] @@ -77,6 +89,8 @@ pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, } #[derive(LintDiagnostic)] @@ -85,6 +99,8 @@ pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, } #[derive(LintDiagnostic)] @@ -93,6 +109,8 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, } #[derive(LintDiagnostic)] @@ -100,6 +118,8 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, } #[derive(LintDiagnostic)] @@ -109,6 +129,8 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedLintNote>, } #[derive(Diagnostic)] @@ -376,6 +398,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<F>(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 { @@ -789,6 +832,18 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> { pub uncovered: Uncovered<'tcx>, } +#[derive(LintDiagnostic)] +#[diag(mir_build_non_exhaustive_omitted_pattern_lint_on_arm)] +#[help] +pub(crate) struct NonExhaustiveOmittedPatternLintOnArm { + #[label] + pub lint_span: Span, + #[suggestion(code = "#[{lint_level}({lint_name})]\n", applicability = "maybe-incorrect")] + pub suggest_lint_on_match: Option<Span>, + pub lint_level: &'static str, + pub lint_name: &'static str, +} + #[derive(Subdiagnostic)] #[label(mir_build_uncovered)] pub(crate) struct Uncovered<'tcx> { diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index b6adb383fa6..bcd9140f0e1 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -132,7 +132,7 @@ 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( 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 933653e708e..8c3d09c19a1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -9,9 +9,7 @@ use rustc_arena::TypedArena; use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::{ - struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, -}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::*; use rustc_hir::def_id::LocalDefId; @@ -44,7 +42,7 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err for param in thir.params.iter() { if let Some(box ref pattern) = param.pat { - visitor.check_irrefutable(pattern, "function argument", None); + visitor.check_binding_is_irrefutable(pattern, "function argument", None); } } visitor.error @@ -58,7 +56,7 @@ fn create_e0004( struct_span_err!(sess, sp, E0004, "{}", &error_message) } -#[derive(PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq)] enum RefutableFlag { Irrefutable, Refutable, @@ -68,24 +66,30 @@ use RefutableFlag::*; #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum LetSource { None, + PlainLet, IfLet, IfLetGuard, LetElse, WhileLet, } -struct MatchVisitor<'a, 'p, 'tcx> { +struct MatchVisitor<'thir, 'p, 'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - thir: &'a Thir<'tcx>, + thir: &'thir Thir<'tcx>, lint_level: HirId, let_source: LetSource, pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>, + /// Tracks if we encountered an error while checking this body. That the first function to + /// report it stores it here. Some functions return `Result` to allow callers to short-circuit + /// on error, but callers don't need to store it here again. error: Result<(), ErrorGuaranteed>, } -impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> { - fn thir(&self) -> &'a Thir<'tcx> { +// Visitor for a thir body. This calls `check_match`, `check_let` and `check_let_chain` as +// appropriate. +impl<'thir, 'tcx> Visitor<'thir, 'tcx> for MatchVisitor<'thir, '_, 'tcx> { + fn thir(&self) -> &'thir Thir<'tcx> { self.thir } @@ -100,7 +104,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> { } Some(Guard::IfLet(ref pat, expr)) => { this.with_let_source(LetSource::IfLetGuard, |this| { - this.check_let(pat, expr, LetSource::IfLetGuard, pat.span); + this.check_let(pat, Some(expr), pat.span); this.visit_pat(pat); this.visit_expr(&this.thir[expr]); }); @@ -148,10 +152,18 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> { self.check_match(scrutinee, arms, source, ex.span); } ExprKind::Let { box ref pat, expr } => { - self.check_let(pat, expr, self.let_source, ex.span); + self.check_let(pat, Some(expr), ex.span); } - ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => { - self.check_let_chain(self.let_source, ex.span, lhs, rhs); + ExprKind::LogicalOp { op: LogicalOp::And, .. } + if !matches!(self.let_source, LetSource::None) => + { + let mut chain_refutabilities = Vec::new(); + let Ok(()) = self.visit_land(ex, &mut chain_refutabilities) else { return }; + // If at least one of the operands is a `let ... = ...`. + if chain_refutabilities.iter().any(|x| x.is_some()) { + self.check_let_chain(chain_refutabilities, ex.span); + } + return; } _ => {} }; @@ -159,33 +171,27 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> { } fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) { - let old_lint_level = self.lint_level; match stmt.kind { StmtKind::Let { box ref pattern, initializer, else_block, lint_level, span, .. } => { - if let LintLevel::Explicit(lint_level) = lint_level { - self.lint_level = lint_level; - } - - if let Some(initializer) = initializer - && else_block.is_some() - { - self.check_let(pattern, initializer, LetSource::LetElse, span); - } - - if else_block.is_none() { - self.check_irrefutable(pattern, "local binding", Some(span)); - } + self.with_lint_level(lint_level, |this| { + let let_source = + if else_block.is_some() { LetSource::LetElse } else { LetSource::PlainLet }; + this.with_let_source(let_source, |this| { + this.check_let(pattern, initializer, span) + }); + visit::walk_stmt(this, stmt); + }); + } + StmtKind::Expr { .. } => { + visit::walk_stmt(self, stmt); } - _ => {} } - visit::walk_stmt(self, stmt); - self.lint_level = old_lint_level; } } -impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { +impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> { #[instrument(level = "trace", skip(self, f))] fn with_let_source(&mut self, let_source: LetSource, f: impl FnOnce(&mut Self)) { let old_let_source = self.let_source; @@ -194,53 +200,127 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { self.let_source = old_let_source; } - fn with_lint_level(&mut self, new_lint_level: LintLevel, f: impl FnOnce(&mut Self)) { + fn with_lint_level<T>( + &mut self, + new_lint_level: LintLevel, + f: impl FnOnce(&mut Self) -> T, + ) -> T { if let LintLevel::Explicit(hir_id) = new_lint_level { let old_lint_level = self.lint_level; self.lint_level = hir_id; - f(self); + let ret = f(self); self.lint_level = old_lint_level; + ret } else { - f(self); + f(self) } } - fn check_patterns(&self, pat: &Pat<'tcx>, rf: RefutableFlag) { - pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat)); - check_for_bindings_named_same_as_variants(self, pat, rf); + /// Visit a nested chain of `&&`. Used for if-let chains. This must call `visit_expr` on the + /// subexpressions we are not handling ourselves. + fn visit_land( + &mut self, + ex: &Expr<'tcx>, + accumulator: &mut Vec<Option<(Span, RefutableFlag)>>, + ) -> Result<(), ErrorGuaranteed> { + match ex.kind { + ExprKind::Scope { value, lint_level, .. } => self.with_lint_level(lint_level, |this| { + this.visit_land(&this.thir[value], accumulator) + }), + ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => { + // We recurse into the lhs only, because `&&` chains associate to the left. + let res_lhs = self.visit_land(&self.thir[lhs], accumulator); + let res_rhs = self.visit_land_rhs(&self.thir[rhs])?; + accumulator.push(res_rhs); + res_lhs + } + _ => { + let res = self.visit_land_rhs(ex)?; + accumulator.push(res); + Ok(()) + } + } + } + + /// Visit the right-hand-side of a `&&`. Used for if-let chains. Returns `Some` if the + /// expression was ultimately a `let ... = ...`, and `None` if it was a normal boolean + /// expression. This must call `visit_expr` on the subexpressions we are not handling ourselves. + fn visit_land_rhs( + &mut self, + ex: &Expr<'tcx>, + ) -> Result<Option<(Span, RefutableFlag)>, ErrorGuaranteed> { + match ex.kind { + ExprKind::Scope { value, lint_level, .. } => { + self.with_lint_level(lint_level, |this| this.visit_land_rhs(&this.thir[value])) + } + ExprKind::Let { box ref pat, expr } => { + self.with_let_source(LetSource::None, |this| { + this.visit_expr(&this.thir()[expr]); + }); + Ok(Some((ex.span, self.is_let_irrefutable(pat)?))) + } + _ => { + self.with_let_source(LetSource::None, |this| { + this.visit_expr(ex); + }); + Ok(None) + } + } } fn lower_pattern( - &self, - cx: &mut MatchCheckCtxt<'p, 'tcx>, - pattern: &Pat<'tcx>, - ) -> &'p DeconstructedPat<'p, 'tcx> { - cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern)) + &mut self, + cx: &MatchCheckCtxt<'p, 'tcx>, + pat: &Pat<'tcx>, + ) -> Result<&'p DeconstructedPat<'p, 'tcx>, ErrorGuaranteed> { + if let Err(err) = pat.pat_error_reported() { + self.error = Err(err); + Err(err) + } 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)); + Ok(cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, pat))) + } } - fn new_cx(&self, hir_id: HirId, refutable: bool) -> MatchCheckCtxt<'p, 'tcx> { + fn new_cx( + &self, + refutability: RefutableFlag, + match_span: Option<Span>, + ) -> MatchCheckCtxt<'p, 'tcx> { + let refutable = match refutability { + Irrefutable => false, + Refutable => true, + }; MatchCheckCtxt { tcx: self.tcx, param_env: self.param_env, - module: self.tcx.parent_module(hir_id).to_def_id(), + module: self.tcx.parent_module(self.lint_level).to_def_id(), pattern_arena: &self.pattern_arena, + match_span, refutable, } } #[instrument(level = "trace", skip(self))] - fn check_let(&mut self, pat: &Pat<'tcx>, scrutinee: ExprId, source: LetSource, span: Span) { - if let LetSource::None = source { - return; - } - if let Err(err) = pat.pat_error_reported() { - self.error = Err(err); - return; + fn check_let(&mut self, pat: &Pat<'tcx>, scrutinee: Option<ExprId>, span: Span) { + assert!(self.let_source != LetSource::None); + if let LetSource::PlainLet = self.let_source { + self.check_binding_is_irrefutable(pat, "local binding", Some(span)) + } else { + let Ok(refutability) = self.is_let_irrefutable(pat) else { return }; + if matches!(refutability, Irrefutable) { + report_irrefutable_let_patterns( + self.tcx, + self.lint_level, + self.let_source, + 1, + span, + ); + } } - self.check_patterns(pat, Refutable); - let mut cx = self.new_cx(self.lint_level, true); - let tpat = self.lower_pattern(&mut cx, pat); - self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span); } fn check_match( @@ -250,33 +330,22 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { source: hir::MatchSource, expr_span: Span, ) { - let mut cx = self.new_cx(self.lint_level, true); + let cx = self.new_cx(Refutable, Some(expr_span)); + let mut tarms = Vec::with_capacity(arms.len()); for &arm in arms { - // Check the arm for some things unrelated to exhaustiveness. let arm = &self.thir.arms[arm]; - self.with_lint_level(arm.lint_level, |this| { - this.check_patterns(&arm.pattern, Refutable); + let got_error = self.with_lint_level(arm.lint_level, |this| { + let Ok(pat) = this.lower_pattern(&cx, &arm.pattern) else { return true }; + let arm = MatchArm { pat, hir_id: this.lint_level, has_guard: arm.guard.is_some() }; + tarms.push(arm); + false }); - if let Err(err) = arm.pattern.pat_error_reported() { - self.error = Err(err); + if got_error { return; } } - let tarms: Vec<_> = arms - .iter() - .map(|&arm| { - let arm = &self.thir.arms[arm]; - let hir_id = match arm.lint_level { - LintLevel::Explicit(hir_id) => hir_id, - LintLevel::Inherited => self.lint_level, - }; - let pat = self.lower_pattern(&mut cx, &arm.pattern); - MatchArm { pat, hir_id, has_guard: arm.guard.is_some() } - }) - .collect(); - let scrut = &self.thir[scrut]; let scrut_ty = scrut.ty; let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty, scrut.span); @@ -303,118 +372,37 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { debug_assert_eq!(pat.span.desugaring_kind(), Some(DesugaringKind::ForLoop)); let PatKind::Variant { ref subpatterns, .. } = pat.kind else { bug!() }; let [pat_field] = &subpatterns[..] else { bug!() }; - self.check_irrefutable(&pat_field.pattern, "`for` loop binding", None); + self.check_binding_is_irrefutable(&pat_field.pattern, "`for` loop binding", None); } else { - self.error = Err(non_exhaustive_match( + self.error = Err(report_non_exhaustive_match( &cx, self.thir, scrut_ty, scrut.span, witnesses, arms, expr_span, )); } } } - fn check_let_reachability( - &mut self, - cx: &mut MatchCheckCtxt<'p, 'tcx>, - pat_id: HirId, - source: LetSource, - pat: &'p DeconstructedPat<'p, 'tcx>, - span: Span, - ) { - if is_let_irrefutable(cx, pat_id, pat) { - irrefutable_let_patterns(cx.tcx, pat_id, source, 1, span); - } - } - #[instrument(level = "trace", skip(self))] fn check_let_chain( &mut self, - let_source: LetSource, - top_expr_span: Span, - mut lhs: ExprId, - rhs: ExprId, + chain_refutabilities: Vec<Option<(Span, RefutableFlag)>>, + whole_chain_span: Span, ) { - if let LetSource::None = let_source { - return; - } - - // Lint level enclosing the next `lhs`. - let mut cur_lint_level = self.lint_level; - - // Obtain the refutabilities of all exprs in the chain, - // and record chain members that aren't let exprs. - let mut chain_refutabilities = Vec::new(); - - let mut error = Ok(()); - let mut add = |expr: ExprId, mut local_lint_level| { - // `local_lint_level` is the lint level enclosing the pattern inside `expr`. - let mut expr = &self.thir[expr]; - debug!(?expr, ?local_lint_level, "add"); - // Fast-forward through scopes. - while let ExprKind::Scope { value, lint_level, .. } = expr.kind { - if let LintLevel::Explicit(hir_id) = lint_level { - local_lint_level = hir_id - } - expr = &self.thir[value]; - } - debug!(?expr, ?local_lint_level, "after scopes"); - match expr.kind { - ExprKind::Let { box ref pat, expr: _ } => { - if let Err(err) = pat.pat_error_reported() { - error = Err(err); - return None; - } - let mut ncx = self.new_cx(local_lint_level, true); - let tpat = self.lower_pattern(&mut ncx, pat); - let refutable = !is_let_irrefutable(&mut ncx, local_lint_level, tpat); - Some((expr.span, refutable)) - } - _ => None, - } - }; - - // Let chains recurse on the left, so we start by adding the rightmost. - chain_refutabilities.push(add(rhs, cur_lint_level)); + assert!(self.let_source != LetSource::None); - loop { - while let ExprKind::Scope { value, lint_level, .. } = self.thir[lhs].kind { - if let LintLevel::Explicit(hir_id) = lint_level { - cur_lint_level = hir_id - } - lhs = value; - } - if let ExprKind::LogicalOp { op: LogicalOp::And, lhs: new_lhs, rhs: expr } = - self.thir[lhs].kind - { - chain_refutabilities.push(add(expr, cur_lint_level)); - lhs = new_lhs; - } else { - chain_refutabilities.push(add(lhs, cur_lint_level)); - break; - } - } - debug!(?chain_refutabilities); - chain_refutabilities.reverse(); - - if error.is_err() { - self.error = error; - return; - } - - // Third, emit the actual warnings. - if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, false)))) { + if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, Irrefutable)))) { // The entire chain is made up of irrefutable `let` statements - irrefutable_let_patterns( + report_irrefutable_let_patterns( self.tcx, self.lint_level, - let_source, + self.let_source, chain_refutabilities.len(), - top_expr_span, + whole_chain_span, ); return; } if let Some(until) = - chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) + chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, Irrefutable)))) && until > 0 { // The chain has a non-zero prefix of irrefutable `let` statements. @@ -425,7 +413,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { // so can't always be moved out. // FIXME: Add checking whether the bindings are actually used in the prefix, // and lint if they are not. - if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) { + if !matches!(self.let_source, LetSource::WhileLet | LetSource::IfLetGuard) { // Emit the lint let prefix = &chain_refutabilities[..until]; let span_start = prefix[0].unwrap().0; @@ -442,7 +430,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } if let Some(from) = - chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, false)))) + chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, Irrefutable)))) && from != (chain_refutabilities.len() - 1) { // The chain has a non-empty suffix of irrefutable `let` statements @@ -460,28 +448,36 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } } - #[instrument(level = "trace", skip(self))] - fn check_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option<Span>) { - // If we got errors while lowering, don't emit anything more. - if let Err(err) = pat.pat_error_reported() { - self.error = Err(err); - return; - } + fn analyze_binding( + &mut self, + pat: &Pat<'tcx>, + refutability: RefutableFlag, + ) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> { + let cx = self.new_cx(refutability, None); + 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()); + Ok((cx, report)) + } - let mut cx = self.new_cx(self.lint_level, false); + fn is_let_irrefutable(&mut self, pat: &Pat<'tcx>) -> Result<RefutableFlag, ErrorGuaranteed> { + let (cx, report) = self.analyze_binding(pat, Refutable)?; + // Report if the pattern is unreachable, which can only occur when the type is uninhabited. + // This also reports unreachable sub-patterns. + report_arm_reachability(&cx, &report); + // If the list of witnesses is empty, the match is exhaustive, i.e. the `if let` pattern is + // irrefutable. + Ok(if report.non_exhaustiveness_witnesses.is_empty() { Irrefutable } else { Refutable }) + } - let pattern = self.lower_pattern(&mut cx, pat); - let pattern_ty = pattern.ty(); - let arm = MatchArm { pat: pattern, hir_id: self.lint_level, has_guard: false }; - let report = - compute_match_usefulness(&cx, &[arm], self.lint_level, pattern_ty, pattern.span()); + #[instrument(level = "trace", skip(self))] + fn check_binding_is_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option<Span>) { + let pattern_ty = pat.ty; - // Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We - // only care about exhaustiveness here. + let Ok((cx, report)) = self.analyze_binding(pat, Irrefutable) else { return }; let witnesses = report.non_exhaustiveness_witnesses; if witnesses.is_empty() { // The pattern is irrefutable. - self.check_patterns(pat, Irrefutable); return; } @@ -528,30 +524,20 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { }); }; - let adt_defined_here = try { - let ty = pattern_ty.peel_refs(); - let ty::Adt(def, _) = ty.kind() else { None? }; - let adt_def_span = cx.tcx.hir().get_if_local(def.did())?.ident()?.span; - let mut variants = vec![]; - - for span in maybe_point_at_variant(&cx, *def, witnesses.iter().take(5)) { - variants.push(Variant { span }); - } - AdtDefinedHere { adt_def_span, ty, variants } - }; + let adt_defined_here = report_adt_defined_here(self.tcx, pattern_ty, &witnesses, false); // Emit an extra note if the first uncovered witness would be uninhabited // if we disregard visibility. - let witness_1_is_privately_uninhabited = if cx.tcx.features().exhaustive_patterns + let witness_1_is_privately_uninhabited = if self.tcx.features().exhaustive_patterns && let Some(witness_1) = witnesses.get(0) && let ty::Adt(adt, args) = witness_1.ty().kind() && adt.is_enum() && let Constructor::Variant(variant_index) = witness_1.ctor() { let variant = adt.variant(*variant_index); - let inhabited = variant.inhabited_predicate(cx.tcx, *adt).instantiate(cx.tcx, args); - assert!(inhabited.apply(cx.tcx, cx.param_env, cx.module)); - !inhabited.apply_ignore_module(cx.tcx, cx.param_env) + let inhabited = variant.inhabited_predicate(self.tcx, *adt).instantiate(self.tcx, args); + assert!(inhabited.apply(self.tcx, cx.param_env, cx.module)); + !inhabited.apply_ignore_module(self.tcx, cx.param_env) } else { false }; @@ -572,70 +558,154 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } } -fn check_for_bindings_named_same_as_variants( - cx: &MatchVisitor<'_, '_, '_>, - pat: &Pat<'_>, - rf: RefutableFlag, -) { - pat.walk_always(|p| { - if let PatKind::Binding { - name, - mode: BindingMode::ByValue, - mutability: Mutability::Not, - subpattern: None, - ty, - .. - } = p.kind - && let ty::Adt(edef, _) = ty.peel_refs().kind() - && edef.is_enum() - && edef - .variants() - .iter() - .any(|variant| variant.name == name && variant.ctor_kind() == Some(CtorKind::Const)) - { - let variant_count = edef.variants().len(); - let ty_path = with_no_trimmed_paths!(cx.tcx.def_path_str(edef.did())); - cx.tcx.emit_spanned_lint( - BINDINGS_WITH_VARIANT_NAME, - cx.lint_level, - p.span, - BindingsWithVariantName { - // If this is an irrefutable pattern, and there's > 1 variant, - // then we can't actually match on this. Applying the below - // suggestion would produce code that breaks on `check_irrefutable`. - suggestion: if rf == Refutable || variant_count == 1 { - Some(p.span) - } else { - None - }, - ty_path, +/// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`. +/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns. +/// +/// For example, this would reject: +/// - `ref x @ Some(ref mut y)`, +/// - `ref mut x @ Some(ref y)`, +/// - `ref mut x @ Some(ref mut y)`, +/// - `ref mut? x @ Some(y)`, and +/// - `x @ Some(ref mut? y)`. +/// +/// This analysis is *not* subsumed by NLL. +fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, pat: &Pat<'tcx>) { + // Extract `sub` in `binding @ sub`. + let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else { + return; + }; + + let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); + + let sess = cx.tcx.sess; + + // Get the binding move, extract the mutability if by-ref. + let mut_outer = match mode { + BindingMode::ByValue if is_binding_by_move(ty) => { + // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. + let mut conflicts_ref = Vec::new(); + sub.each_binding(|_, mode, _, span| match mode { + BindingMode::ByValue => {} + BindingMode::ByRef(_) => conflicts_ref.push(span), + }); + if !conflicts_ref.is_empty() { + sess.emit_err(BorrowOfMovedValue { + binding_span: pat.span, + conflicts_ref, name, - }, - ) + ty, + suggest_borrowing: Some(pat.span.shrink_to_lo()), + }); + } + return; + } + BindingMode::ByValue => return, + BindingMode::ByRef(m) => m.mutability(), + }; + + // We now have `ref $mut_outer binding @ sub` (semantically). + // Recurse into each binding in `sub` and find mutability or move conflicts. + let mut conflicts_move = Vec::new(); + let mut conflicts_mut_mut = Vec::new(); + let mut conflicts_mut_ref = Vec::new(); + sub.each_binding(|name, mode, ty, span| { + match mode { + BindingMode::ByRef(mut_inner) => match (mut_outer, mut_inner.mutability()) { + // Both sides are `ref`. + (Mutability::Not, Mutability::Not) => {} + // 2x `ref mut`. + (Mutability::Mut, Mutability::Mut) => { + conflicts_mut_mut.push(Conflict::Mut { span, name }) + } + (Mutability::Not, Mutability::Mut) => { + conflicts_mut_ref.push(Conflict::Mut { span, name }) + } + (Mutability::Mut, Mutability::Not) => { + conflicts_mut_ref.push(Conflict::Ref { span, name }) + } + }, + BindingMode::ByValue if is_binding_by_move(ty) => { + conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict. + } + BindingMode::ByValue => {} // `ref mut?` + by-copy is fine. } }); -} -/// Checks for common cases of "catchall" patterns that may not be intended as such. -fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool { - use Constructor::*; - match pat.ctor() { - Wildcard => true, - Single => pat.iter_fields().all(|pat| pat_is_catchall(pat)), - _ => false, + let report_mut_mut = !conflicts_mut_mut.is_empty(); + let report_mut_ref = !conflicts_mut_ref.is_empty(); + let report_move_conflict = !conflicts_move.is_empty(); + + let mut occurrences = match mut_outer { + Mutability::Mut => vec![Conflict::Mut { span: pat.span, name }], + Mutability::Not => vec![Conflict::Ref { span: pat.span, name }], + }; + occurrences.extend(conflicts_mut_mut); + occurrences.extend(conflicts_mut_ref); + occurrences.extend(conflicts_move); + + // Report errors if any. + if report_mut_mut { + // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`. + sess.emit_err(MultipleMutBorrows { span: pat.span, occurrences }); + } else if report_mut_ref { + // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse. + match mut_outer { + Mutability::Mut => { + sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurrences }); + } + Mutability::Not => { + sess.emit_err(AlreadyBorrowed { span: pat.span, occurrences }); + } + }; + } else if report_move_conflict { + // Report by-ref and by-move conflicts, e.g. `ref x @ y`. + sess.emit_err(MovedWhileBorrowed { span: pat.span, occurrences }); } } -fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<Span>) { - tcx.emit_spanned_lint( - UNREACHABLE_PATTERNS, - id, - span, - UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall }, - ); +fn check_for_bindings_named_same_as_variants( + cx: &MatchVisitor<'_, '_, '_>, + pat: &Pat<'_>, + rf: RefutableFlag, +) { + if let PatKind::Binding { + name, + mode: BindingMode::ByValue, + mutability: Mutability::Not, + subpattern: None, + ty, + .. + } = pat.kind + && let ty::Adt(edef, _) = ty.peel_refs().kind() + && edef.is_enum() + && edef + .variants() + .iter() + .any(|variant| variant.name == name && variant.ctor_kind() == Some(CtorKind::Const)) + { + let variant_count = edef.variants().len(); + let ty_path = with_no_trimmed_paths!(cx.tcx.def_path_str(edef.did())); + cx.tcx.emit_spanned_lint( + BINDINGS_WITH_VARIANT_NAME, + cx.lint_level, + pat.span, + BindingsWithVariantName { + // If this is an irrefutable pattern, and there's > 1 variant, + // then we can't actually match on this. Applying the below + // suggestion would produce code that breaks on `check_binding_is_irrefutable`. + suggestion: if rf == Refutable || variant_count == 1 { + Some(pat.span) + } else { + None + }, + ty_path, + name, + }, + ) + } } -fn irrefutable_let_patterns( +fn report_irrefutable_let_patterns( tcx: TyCtxt<'_>, id: HirId, source: LetSource, @@ -649,7 +719,7 @@ fn irrefutable_let_patterns( } match source { - LetSource::None => bug!(), + LetSource::None | LetSource::PlainLet => bug!(), LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet), LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard), LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse), @@ -657,34 +727,28 @@ fn irrefutable_let_patterns( } } -fn is_let_irrefutable<'p, 'tcx>( - cx: &mut MatchCheckCtxt<'p, 'tcx>, - pat_id: HirId, - pat: &'p DeconstructedPat<'p, 'tcx>, -) -> bool { - let arms = [MatchArm { pat, hir_id: pat_id, has_guard: false }]; - let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty(), pat.span()); - - // Report if the pattern is unreachable, which can only occur when the type is uninhabited. - // This also reports unreachable sub-patterns though, so we can't just replace it with an - // `is_uninhabited` check. - report_arm_reachability(&cx, &report); - - // If the list of witnesses is empty, the match is exhaustive, - // i.e. the `if let` pattern is irrefutable. - report.non_exhaustiveness_witnesses.is_empty() -} - /// Report unreachable arms, if any. fn report_arm_reachability<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, report: &UsefulnessReport<'p, 'tcx>, ) { + let report_unreachable_pattern = |span, hir_id, catchall: Option<Span>| { + cx.tcx.emit_spanned_lint( + UNREACHABLE_PATTERNS, + hir_id, + span, + UnreachablePattern { + span: if catchall.is_some() { Some(span) } else { None }, + catchall, + }, + ); + }; + use Reachability::*; let mut catchall = None; for (arm, is_useful) in report.arm_usefulness.iter() { match is_useful { - Unreachable => unreachable_pattern(cx.tcx, arm.pat.span(), arm.hir_id, catchall), + Unreachable => report_unreachable_pattern(arm.pat.span(), arm.hir_id, catchall), Reachable(unreachables) if unreachables.is_empty() => {} // The arm is reachable, but contains unreachable subpatterns (from or-patterns). Reachable(unreachables) => { @@ -692,7 +756,7 @@ fn report_arm_reachability<'p, 'tcx>( // Emit lints in the order in which they occur in the file. unreachables.sort_unstable(); for span in unreachables { - unreachable_pattern(cx.tcx, span, arm.hir_id, None); + report_unreachable_pattern(span, arm.hir_id, None); } } } @@ -702,26 +766,18 @@ fn report_arm_reachability<'p, 'tcx>( } } -fn collect_non_exhaustive_tys<'tcx>( - tcx: TyCtxt<'tcx>, - pat: &WitnessPat<'tcx>, - non_exhaustive_tys: &mut FxHashSet<Ty<'tcx>>, -) { - if matches!(pat.ctor(), Constructor::NonExhaustive) { - non_exhaustive_tys.insert(pat.ty()); - } - if let Constructor::IntRange(range) = pat.ctor() { - if range.is_beyond_boundaries(pat.ty(), tcx) { - // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`. - non_exhaustive_tys.insert(pat.ty()); - } +/// Checks for common cases of "catchall" patterns that may not be intended as such. +fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool { + use Constructor::*; + match pat.ctor() { + Wildcard => true, + Single => pat.iter_fields().all(|pat| pat_is_catchall(pat)), + _ => false, } - pat.iter_fields() - .for_each(|field_pat| collect_non_exhaustive_tys(tcx, field_pat, non_exhaustive_tys)) } /// Report that a match is not exhaustive. -fn non_exhaustive_match<'p, 'tcx>( +fn report_non_exhaustive_match<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, thir: &Thir<'tcx>, scrut_ty: Ty<'tcx>, @@ -755,7 +811,14 @@ fn non_exhaustive_match<'p, 'tcx>( sp, format!("non-exhaustive patterns: {joined_patterns} not covered"), ); - err.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns)); + err.span_label( + sp, + format!( + "pattern{} {} not covered", + rustc_errors::pluralize!(witnesses.len()), + joined_patterns + ), + ); patterns_len = witnesses.len(); pattern = if witnesses.len() < 4 { witnesses @@ -768,7 +831,17 @@ fn non_exhaustive_match<'p, 'tcx>( }; }; - adt_defined_here(cx, &mut err, scrut_ty, &witnesses); + // Point at the definition of non-covered `enum` variants. + if let Some(AdtDefinedHere { adt_def_span, ty, variants }) = + report_adt_defined_here(cx.tcx, scrut_ty, &witnesses, true) + { + let mut multi_span = MultiSpan::from_span(adt_def_span); + multi_span.push_span_label(adt_def_span, ""); + for Variant { span } in variants { + multi_span.push_span_label(span, "not covered"); + } + err.span_note(multi_span, format!("`{ty}` defined here")); + } err.note(format!("the matched value is of type `{}`", scrut_ty)); if !is_empty_match { @@ -910,7 +983,7 @@ fn non_exhaustive_match<'p, 'tcx>( err.emit() } -pub(crate) fn joined_uncovered_patterns<'p, 'tcx>( +fn joined_uncovered_patterns<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, witnesses: &[WitnessPat<'tcx>], ) -> String { @@ -931,48 +1004,51 @@ pub(crate) fn joined_uncovered_patterns<'p, 'tcx>( } } -pub(crate) fn pattern_not_covered_label( - witnesses: &[WitnessPat<'_>], - joined_patterns: &str, -) -> String { - format!("pattern{} {} not covered", rustc_errors::pluralize!(witnesses.len()), joined_patterns) +fn collect_non_exhaustive_tys<'tcx>( + tcx: TyCtxt<'tcx>, + pat: &WitnessPat<'tcx>, + non_exhaustive_tys: &mut FxHashSet<Ty<'tcx>>, +) { + if matches!(pat.ctor(), Constructor::NonExhaustive) { + non_exhaustive_tys.insert(pat.ty()); + } + if let Constructor::IntRange(range) = pat.ctor() { + if range.is_beyond_boundaries(pat.ty(), tcx) { + // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`. + non_exhaustive_tys.insert(pat.ty()); + } + } + pat.iter_fields() + .for_each(|field_pat| collect_non_exhaustive_tys(tcx, field_pat, non_exhaustive_tys)) } -/// Point at the definition of non-covered `enum` variants. -fn adt_defined_here<'p, 'tcx>( - cx: &MatchCheckCtxt<'p, 'tcx>, - err: &mut Diagnostic, +fn report_adt_defined_here<'tcx>( + tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, witnesses: &[WitnessPat<'tcx>], -) { + point_at_non_local_ty: bool, +) -> Option<AdtDefinedHere<'tcx>> { let ty = ty.peel_refs(); - if let ty::Adt(def, _) = ty.kind() { - let mut spans = vec![]; - if witnesses.len() < 5 { - for sp in maybe_point_at_variant(cx, *def, witnesses.iter()) { - spans.push(sp); - } - } - let def_span = cx - .tcx - .hir() - .get_if_local(def.did()) - .and_then(|node| node.ident()) - .map(|ident| ident.span) - .unwrap_or_else(|| cx.tcx.def_span(def.did())); - let mut span: MultiSpan = - if spans.is_empty() { def_span.into() } else { spans.clone().into() }; - - span.push_span_label(def_span, ""); - for pat in spans { - span.push_span_label(pat, "not covered"); - } - err.span_note(span, format!("`{ty}` defined here")); + let ty::Adt(def, _) = ty.kind() else { + return None; + }; + let adt_def_span = + tcx.hir().get_if_local(def.did()).and_then(|node| node.ident()).map(|ident| ident.span); + let adt_def_span = if point_at_non_local_ty { + adt_def_span.unwrap_or_else(|| tcx.def_span(def.did())) + } else { + adt_def_span? + }; + + let mut variants = vec![]; + for span in maybe_point_at_variant(tcx, *def, witnesses.iter().take(5)) { + variants.push(Variant { span }); } + Some(AdtDefinedHere { adt_def_span, ty, variants }) } -fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( - cx: &MatchCheckCtxt<'p, 'tcx>, +fn maybe_point_at_variant<'a, 'tcx: 'a>( + tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, patterns: impl Iterator<Item = &'a WitnessPat<'tcx>>, ) -> Vec<Span> { @@ -985,7 +1061,7 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( { continue; } - let sp = def.variant(*variant_index).ident(cx.tcx).span; + let sp = def.variant(*variant_index).ident(tcx).span; if covered.contains(&sp) { // Don't point at variants that have already been covered due to other patterns to avoid // visual clutter. @@ -993,112 +1069,7 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( } covered.push(sp); } - covered.extend(maybe_point_at_variant(cx, def, pattern.iter_fields())); + covered.extend(maybe_point_at_variant(tcx, def, pattern.iter_fields())); } covered } - -/// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`. -/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns. -/// -/// For example, this would reject: -/// - `ref x @ Some(ref mut y)`, -/// - `ref mut x @ Some(ref y)`, -/// - `ref mut x @ Some(ref mut y)`, -/// - `ref mut? x @ Some(y)`, and -/// - `x @ Some(ref mut? y)`. -/// -/// This analysis is *not* subsumed by NLL. -fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, pat: &Pat<'tcx>) { - // Extract `sub` in `binding @ sub`. - let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else { - return; - }; - - let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); - - let sess = cx.tcx.sess; - - // Get the binding move, extract the mutability if by-ref. - let mut_outer = match mode { - BindingMode::ByValue if is_binding_by_move(ty) => { - // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. - let mut conflicts_ref = Vec::new(); - sub.each_binding(|_, mode, _, span| match mode { - BindingMode::ByValue => {} - BindingMode::ByRef(_) => conflicts_ref.push(span), - }); - if !conflicts_ref.is_empty() { - sess.emit_err(BorrowOfMovedValue { - binding_span: pat.span, - conflicts_ref, - name, - ty, - suggest_borrowing: Some(pat.span.shrink_to_lo()), - }); - } - return; - } - BindingMode::ByValue => return, - BindingMode::ByRef(m) => m.mutability(), - }; - - // We now have `ref $mut_outer binding @ sub` (semantically). - // Recurse into each binding in `sub` and find mutability or move conflicts. - let mut conflicts_move = Vec::new(); - let mut conflicts_mut_mut = Vec::new(); - let mut conflicts_mut_ref = Vec::new(); - sub.each_binding(|name, mode, ty, span| { - match mode { - BindingMode::ByRef(mut_inner) => match (mut_outer, mut_inner.mutability()) { - // Both sides are `ref`. - (Mutability::Not, Mutability::Not) => {} - // 2x `ref mut`. - (Mutability::Mut, Mutability::Mut) => { - conflicts_mut_mut.push(Conflict::Mut { span, name }) - } - (Mutability::Not, Mutability::Mut) => { - conflicts_mut_ref.push(Conflict::Mut { span, name }) - } - (Mutability::Mut, Mutability::Not) => { - conflicts_mut_ref.push(Conflict::Ref { span, name }) - } - }, - BindingMode::ByValue if is_binding_by_move(ty) => { - conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict. - } - BindingMode::ByValue => {} // `ref mut?` + by-copy is fine. - } - }); - - let report_mut_mut = !conflicts_mut_mut.is_empty(); - let report_mut_ref = !conflicts_mut_ref.is_empty(); - let report_move_conflict = !conflicts_move.is_empty(); - - let mut occurrences = match mut_outer { - Mutability::Mut => vec![Conflict::Mut { span: pat.span, name }], - Mutability::Not => vec![Conflict::Ref { span: pat.span, name }], - }; - occurrences.extend(conflicts_mut_mut); - occurrences.extend(conflicts_mut_ref); - occurrences.extend(conflicts_move); - - // Report errors if any. - if report_mut_mut { - // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`. - sess.emit_err(MultipleMutBorrows { span: pat.span, occurrences }); - } else if report_mut_ref { - // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse. - match mut_outer { - Mutability::Mut => { - sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurrences }); - } - Mutability::Not => { - sess.emit_err(AlreadyBorrowed { span: pat.span, occurrences }); - } - }; - } else if report_move_conflict { - // Report by-ref and by-move conflicts, e.g. `ref x @ y`. - sess.emit_err(MovedWhileBorrowed { span: pat.span, occurrences }); - } -} 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 fc03f7891a8..48a590f5d37 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(_) @@ -209,16 +211,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 +228,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 @@ -389,11 +377,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 +476,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/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 1eb1dd72a61..da7b6587a72 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -311,7 +311,10 @@ use super::deconstruct_pat::{ Constructor, ConstructorSet, DeconstructedPat, IntRange, MaybeInfiniteInt, SplitConstructorSet, WitnessPat, }; -use crate::errors::{NonExhaustiveOmittedPattern, Overlap, OverlappingRangeEndpoints, Uncovered}; +use crate::errors::{ + NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Overlap, + OverlappingRangeEndpoints, Uncovered, +}; use rustc_data_structures::captures::Captures; @@ -337,6 +340,8 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> { pub(crate) module: DefId, pub(crate) param_env: ty::ParamEnv<'tcx>, pub(crate) pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>, + /// The span of the whole match, if applicable. + pub(crate) match_span: Option<Span>, /// Only produce `NON_EXHAUSTIVE_OMITTED_PATTERNS` lint on refutable patterns. pub(crate) refutable: bool, } @@ -1149,28 +1154,50 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>( // 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() - && !matches!( + if cx.refutable && non_exhaustiveness_witnesses.is_empty() { + if !matches!( cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, lint_root).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. - // - // 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, - NonExhaustiveOmittedPattern { - scrut_ty, - uncovered: Uncovered::new(scrut_span, cx, witnesses), - }, - ); + ) { + 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. + // + // 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, + NonExhaustiveOmittedPattern { + scrut_ty, + uncovered: Uncovered::new(scrut_span, cx, witnesses), + }, + ); + } + } else { + // We used to allow putting the `#[allow(non_exhaustive_omitted_patterns)]` on a match + // arm. This no longer makes sense so we warn users, to avoid silently breaking their + // usage of the lint. + for arm in arms { + let (lint_level, lint_level_source) = + cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id); + if !matches!(lint_level, rustc_session::lint::Level::Allow) { + let decorator = NonExhaustiveOmittedPatternLintOnArm { + lint_span: lint_level_source.span(), + suggest_lint_on_match: cx.match_span.map(|span| span.shrink_to_lo()), + lint_level: lint_level.as_str(), + lint_name: "non_exhaustive_omitted_patterns", + }; + + use rustc_errors::DecorateLint; + let mut err = cx.tcx.sess.struct_span_warn(arm.pat.span(), ""); + err.set_primary_message(decorator.msg()); + decorator.decorate_lint(&mut err); + err.emit(); + } + } } } diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 1e8e09ac333..01acc380fa3 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/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index c1152e88cd0..bdfb6a6ff6b 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -201,7 +201,7 @@ impl DefUse { | NonMutatingUseContext::Inspect | NonMutatingUseContext::Move | NonMutatingUseContext::PlaceMention - | NonMutatingUseContext::ShallowBorrow + | NonMutatingUseContext::FakeBorrow | NonMutatingUseContext::SharedBorrow, ) => Some(DefUse::Use), diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 28765af20ad..42b2f18869c 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -1,13 +1,12 @@ use crate::MirPass; -use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_index::IndexVec; use rustc_middle::mir::*; use rustc_middle::mir::{ interpret::Scalar, - visit::{PlaceContext, Visitor}, + visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}, }; -use rustc_middle::ty::{Ty, TyCtxt, TypeAndMut}; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeAndMut}; use rustc_session::Session; pub struct CheckAlignment; @@ -30,7 +29,12 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment { let basic_blocks = body.basic_blocks.as_mut(); let local_decls = &mut body.local_decls; + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + // This pass inserts new blocks. Each insertion changes the Location for all + // statements/blocks after. Iterating or visiting the MIR in order would require updating + // our current location after every insertion. By iterating backwards, we dodge this issue: + // The only Locations that an insertion changes have already been handled. for block in (0..basic_blocks.len()).rev() { let block = block.into(); for statement_index in (0..basic_blocks[block].statements.len()).rev() { @@ -38,22 +42,19 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment { let statement = &basic_blocks[block].statements[statement_index]; let source_info = statement.source_info; - let mut finder = PointerFinder { - local_decls, - tcx, - pointers: Vec::new(), - def_id: body.source.def_id(), - }; - for (pointer, pointee_ty) in finder.find_pointers(statement) { - debug!("Inserting alignment check for {:?}", pointer.ty(&*local_decls, tcx).ty); + let mut finder = + PointerFinder { tcx, local_decls, param_env, pointers: Vec::new() }; + finder.visit_statement(statement, location); + for (local, ty) in finder.pointers { + debug!("Inserting alignment check for {:?}", ty); let new_block = split_block(basic_blocks, location); insert_alignment_check( tcx, local_decls, &mut basic_blocks[block], - pointer, - pointee_ty, + local, + ty, source_info, new_block, ); @@ -63,69 +64,71 @@ impl<'tcx> MirPass<'tcx> for CheckAlignment { } } -impl<'tcx, 'a> PointerFinder<'tcx, 'a> { - fn find_pointers(&mut self, statement: &Statement<'tcx>) -> Vec<(Place<'tcx>, Ty<'tcx>)> { - self.pointers.clear(); - self.visit_statement(statement, Location::START); - core::mem::take(&mut self.pointers) - } -} - struct PointerFinder<'tcx, 'a> { - local_decls: &'a mut LocalDecls<'tcx>, tcx: TyCtxt<'tcx>, - def_id: DefId, + local_decls: &'a mut LocalDecls<'tcx>, + param_env: ParamEnv<'tcx>, pointers: Vec<(Place<'tcx>, Ty<'tcx>)>, } impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> { - fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { - if let Rvalue::AddressOf(..) = rvalue { - // Ignore dereferences inside of an AddressOf - return; + fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { + // We want to only check reads and writes to Places, so we specifically exclude + // Borrows and AddressOf. + match context { + PlaceContext::MutatingUse( + MutatingUseContext::Store + | MutatingUseContext::AsmOutput + | MutatingUseContext::Call + | MutatingUseContext::Yield + | MutatingUseContext::Drop, + ) => {} + PlaceContext::NonMutatingUse( + NonMutatingUseContext::Copy | NonMutatingUseContext::Move, + ) => {} + _ => { + return; + } } - self.super_rvalue(rvalue, location); - } - fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { - if let PlaceContext::NonUse(_) = context { - return; - } if !place.is_indirect() { return; } + // Since Deref projections must come first and only once, the pointer for an indirect place + // is the Local that the Place is based on. let pointer = Place::from(place.local); - let pointer_ty = pointer.ty(&*self.local_decls, self.tcx).ty; + let pointer_ty = self.local_decls[place.local].ty; - // We only want to check unsafe pointers + // We only want to check places based on unsafe pointers if !pointer_ty.is_unsafe_ptr() { - trace!("Indirect, but not an unsafe ptr, not checking {:?}", pointer_ty); + trace!("Indirect, but not based on an unsafe ptr, not checking {:?}", place); return; } - let Some(pointee) = pointer_ty.builtin_deref(true) else { - debug!("Indirect but no builtin deref: {:?}", pointer_ty); + let pointee_ty = + pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer").ty; + // Ideally we'd support this in the future, but for now we are limited to sized types. + if !pointee_ty.is_sized(self.tcx, self.param_env) { + debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty); return; - }; - let mut pointee_ty = pointee.ty; - if pointee_ty.is_array() || pointee_ty.is_slice() || pointee_ty.is_str() { - pointee_ty = pointee_ty.sequence_element_type(self.tcx); } - if !pointee_ty.is_sized(self.tcx, self.tcx.param_env_reveal_all_normalized(self.def_id)) { - debug!("Unsafe pointer, but unsized: {:?}", pointer_ty); + // Try to detect types we are sure have an alignment of 1 and skip the check + // We don't need to look for str and slices, we already rejected unsized types above + let element_ty = match pointee_ty.kind() { + ty::Array(ty, _) => *ty, + _ => pointee_ty, + }; + if [self.tcx.types.bool, self.tcx.types.i8, self.tcx.types.u8].contains(&element_ty) { + debug!("Trivially aligned place type: {:?}", pointee_ty); return; } - if [self.tcx.types.bool, self.tcx.types.i8, self.tcx.types.u8, self.tcx.types.str_] - .contains(&pointee_ty) - { - debug!("Trivially aligned pointee type: {:?}", pointer_ty); - return; - } + // Ensure that this place is based on an aligned pointer. + self.pointers.push((pointer, pointee_ty)); - self.pointers.push((pointer, pointee_ty)) + self.super_place(place, context, location); } } diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index d435d3ee69b..5b4bc4fa134 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 53c0d0dea29..0adbb078105 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -668,7 +668,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) => { diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index be4af3b76f1..f5db7ce97eb 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -131,7 +131,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { 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 fc30a718cbb..dfafd859830 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -637,6 +637,14 @@ struct LivenessInfo { storage_liveness: IndexVec<BasicBlock, Option<BitSet<Local>>>, } +/// 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>, @@ -1449,16 +1457,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` diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 704eea413e1..b318134ae67 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -381,6 +381,12 @@ impl<'a> CoverageSpansGenerator<'a> { 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); + if self.curr().span.lo() + after_macro_bang > self.curr().span.hi() { + // Something is wrong with the macro name span; + // return now to avoid emitting malformed mappings. + // FIXME(#117788): Track down why this happens. + 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 = diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 4d0e261ed1f..261d9dd448d 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/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 5aa3c3cfe4d..9f59f9d1245 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/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 427cc1e1924..7de4ca66794 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; } diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 8dc7b60c4e5..3a6e1ef3488 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<Item = (Local, &'a Rvalue<'tcx>, 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<BasicBlock>, assignments: IndexVec<Local, Set1<DefLocation>>, assignment_order: Vec<Local>, direct_uses: IndexVec<Local, u32>, } -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_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index e51b672205c..266190da035 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -270,6 +270,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}` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 20b4292701e..8ab1ec298a1 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1378,6 +1378,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<F>(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( diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 31d91fe80bd..db795ce9f72 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>, @@ -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 @@ -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<PErr<'a>>) -> Vec<PErr<'a>> { + // 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). diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 36125e138b2..235b28b6e26 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2303,13 +2303,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)) } else { - Ok(CaptureBy::Value) + Ok(CaptureBy::Value { move_kw: move_kw_span }) } } else { Ok(CaptureBy::Ref) @@ -2440,10 +2441,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 })? } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 253dd2a3b34..801860c2123 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2278,6 +2278,18 @@ impl<'a> Parser<'a> { err.span_label(ident.span, "while parsing this `fn`"); err.emit(); } else { + // check for typo'd Fn* trait bounds such as + // fn foo<F>() where F: FnOnce -> () {} + if self.token.kind == token::RArrow { + let machine_applicable = [sym::FnOnce, sym::FnMut, sym::Fn] + .into_iter() + .any(|s| self.prev_token.is_ident_named(s)); + + err.subdiagnostic(errors::FnTraitMissingParen { + span: self.prev_token.span, + machine_applicable, + }); + } return Err(err); } } @@ -2389,22 +2401,39 @@ impl<'a> Parser<'a> { Misplaced(Span), } + // We may be able to recover + let mut recover_constness = constness; + let mut recover_asyncness = asyncness; + let mut recover_unsafety = unsafety; // This will allow the machine fix to directly place the keyword in the correct place or to indicate // that the keyword is already present and the second instance should be removed. let wrong_kw = if self.check_keyword(kw::Const) { match constness { Const::Yes(sp) => Some(WrongKw::Duplicated(sp)), - Const::No => Some(WrongKw::Misplaced(async_start_sp)), + Const::No => { + recover_constness = Const::Yes(self.token.span); + Some(WrongKw::Misplaced(async_start_sp)) + } } } else if self.check_keyword(kw::Async) { match asyncness { Async::Yes { span, .. } => Some(WrongKw::Duplicated(span)), - Async::No => Some(WrongKw::Misplaced(unsafe_start_sp)), + Async::No => { + recover_asyncness = Async::Yes { + span: self.token.span, + closure_id: DUMMY_NODE_ID, + return_impl_trait_id: DUMMY_NODE_ID, + }; + Some(WrongKw::Misplaced(unsafe_start_sp)) + } } } else if self.check_keyword(kw::Unsafe) { match unsafety { Unsafe::Yes(sp) => Some(WrongKw::Duplicated(sp)), - Unsafe::No => Some(WrongKw::Misplaced(ext_start_sp)), + Unsafe::No => { + recover_unsafety = Unsafe::Yes(self.token.span); + Some(WrongKw::Misplaced(ext_start_sp)) + } } } else { None @@ -2474,6 +2503,23 @@ impl<'a> Parser<'a> { } } } + + if wrong_kw.is_some() + && self.may_recover() + && self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case)) + { + // Advance past the misplaced keyword and `fn` + self.bump(); + self.bump(); + err.emit(); + return Ok(FnHeader { + constness: recover_constness, + unsafety: recover_unsafety, + asyncness: recover_asyncness, + ext, + }); + } + return Err(err); } } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 1a7ae406911..76f3f21a516 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1115,7 +1115,7 @@ impl<'a> Parser<'a> { } /// Returns whether any of the given keywords are `dist` tokens ahead of the current one. - fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { + pub(crate) fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw))) } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index be2cbaf3020..dc0f1396523 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -135,7 +135,7 @@ impl<'a> Parser<'a> { ) } - /// Parse a type suitable for a field defintion. + /// Parse a type suitable for a field definition. /// The difference from `parse_ty` is that this version /// allows anonymous structs and unions. pub fn parse_ty_for_field_def(&mut self) -> PResult<'a, P<Ty>> { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 2e8c58b0241..6b2b842543a 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -314,7 +314,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { // for the `#[expect]` case. // // Note that an item can and will be duplicated on the worklist with different - // `ComesFromAllowExpect`, particulary if it was added from the + // `ComesFromAllowExpect`, particularly if it was added from the // `effective_visibilities` query or from the `#[allow]`/`#[expect]` checks, // this "duplication" is essential as otherwise a function with `#[expect]` // called from a `pub fn` may be falsely reported as not live, falsely diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4bb7e65747f..4b3b82c59cf 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1756,7 +1756,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> { // fn from(_: Priv) -> Pub {...} // } // - // lints shouldn't be emmited even if `from` effective visibility + // lints shouldn't be emitted even if `from` effective visibility // is larger than `Priv` nominal visibility and if `Priv` can leak // in some scenarios due to type inference. let impl_ev = EffectiveVisibility::of_impl::<false>( diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index edcc22d56c6..93db6cfc463 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1545,7 +1545,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let (span, sugg, post) = if let SuggestionTarget::SimilarlyNamed = suggestion.target && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) && let Some(span) = suggestion.span - && let Some(candidate) = suggestion.candidate.as_str().strip_prefix("_") + && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_') && snippet == candidate { // When the suggested binding change would be from `x` to `_x`, suggest changing the diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index f792b8f2cdd..e1eb58fecc7 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -226,7 +226,7 @@ impl CodeStats { } } - pub fn print_vtable_sizes(&self, crate_name: &str) { + pub fn print_vtable_sizes(&self, crate_name: Symbol) { let mut infos = std::mem::take(&mut *self.vtable_sizes.lock()).into_values().collect::<Vec<_>>(); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c94e0d0ed39..add40b83d21 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2477,7 +2477,7 @@ pub fn parse_externs( let mut error = handler.early_struct_error(format!( "crate name `{name}` passed to `--extern` is not a valid ASCII identifier" )); - let adjusted_name = name.replace("-", "_"); + let adjusted_name = name.replace('-', "_"); if crate::utils::is_ascii_ident(&adjusted_name) { error.help(format!( "consider replacing the dashes with underscores: `{adjusted_name}`" @@ -3161,10 +3161,10 @@ impl PpMode { pub(crate) mod dep_tracking { use super::{ BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression, - ErrorOutputType, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, - LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius, - RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, - SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths, + ErrorOutputType, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, + LocationDetail, LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, + Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, + SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths, }; use crate::lint; use crate::options::WasiExecModel; @@ -3178,9 +3178,8 @@ pub(crate) mod dep_tracking { use rustc_target::spec::{ RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, }; - use std::collections::hash_map::DefaultHasher; use std::collections::BTreeMap; - use std::hash::Hash; + use std::hash::{DefaultHasher, Hash}; use std::num::NonZeroUsize; use std::path::PathBuf; @@ -3270,6 +3269,7 @@ pub(crate) mod dep_tracking { LanguageIdentifier, TraitSolver, Polonius, + InliningThreshold, ); impl<T1, T2> DepTrackingHash for (T1, T2) @@ -3435,3 +3435,16 @@ impl Polonius { matches!(self, Polonius::Next) } } + +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum InliningThreshold { + Always, + Sometimes(usize), + Never, +} + +impl Default for InliningThreshold { + fn default() -> Self { + Self::Sometimes(100) + } +} diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7510a41485a..07712636445 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -19,8 +19,7 @@ use rustc_span::SourceFileHashAlgorithm; use std::collections::BTreeMap; -use std::collections::hash_map::DefaultHasher; -use std::hash::Hasher; +use std::hash::{DefaultHasher, Hasher}; use std::num::{IntErrorKind, NonZeroUsize}; use std::path::PathBuf; use std::str; @@ -428,6 +427,8 @@ mod desc { "one of supported execution strategies (`same-thread`, or `cross-thread`)"; pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`"; pub const parse_remap_path_scope: &str = "comma separated list of scopes: `macro`, `diagnostics`, `unsplit-debuginfo`, `split-debuginfo`, `split-debuginfo-path`, `object`, `all`"; + pub const parse_inlining_threshold: &str = + "either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number"; } mod parse { @@ -1310,6 +1311,26 @@ mod parse { }; true } + + pub(crate) fn parse_inlining_threshold(slot: &mut InliningThreshold, v: Option<&str>) -> bool { + match v { + Some("always" | "yes") => { + *slot = InliningThreshold::Always; + } + Some("never") => { + *slot = InliningThreshold::Never; + } + Some(v) => { + if let Ok(threshold) = v.parse() { + *slot = InliningThreshold::Sometimes(threshold); + } else { + return false; + } + } + None => return false, + } + true + } } options! { @@ -1479,7 +1500,7 @@ options! { "combine CGUs into a single one"), crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), - cross_crate_inline_threshold: Option<usize> = (None, parse_opt_number, [TRACKED], + cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED], "threshold to allow cross crate inlining of functions"), debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], "emit discriminators and other data necessary for AutoFDO"), @@ -1600,8 +1621,6 @@ options! { `=skip-entry` `=skip-exit` Multiple options can be combined with commas."), - keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED], - "keep hygiene data after analysis (default: no)"), layout_seed: Option<u64> = (None, parse_opt_number, [TRACKED], "seed layout randomization"), link_directives: bool = (true, parse_bool, [TRACKED], @@ -1689,8 +1708,6 @@ options! { "panic strategy for panics in drops"), parse_only: bool = (false, parse_bool, [UNTRACKED], "parse only; do not compile, assemble, or link (default: no)"), - perf_stats: bool = (false, parse_bool, [UNTRACKED], - "print some performance-related statistics (default: no)"), plt: Option<bool> = (None, parse_opt_bool, [TRACKED], "whether to use the PLT when calling into shared libraries; only has effect for PIC code on systems with ELF binaries @@ -1819,8 +1836,6 @@ written to standard error output)"), "prefer dynamic linking to static linking for staticlibs (default: no)"), strict_init_checks: bool = (false, parse_bool, [TRACKED], "control if mem::uninitialized and mem::zeroed panic on more UB"), - strip: Strip = (Strip::None, parse_strip, [UNTRACKED], - "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), #[rustc_lint_opt_deny_field_access("use `Session::teach` instead of this field")] teach: bool = (false, parse_bool, [TRACKED], "show extended diagnostic help (default: no)"), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 80a549b30f7..e9655a5587d 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -15,10 +15,8 @@ pub use rustc_ast::Attribute; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::jobserver::{self, Client}; -use rustc_data_structures::profiling::{duration_to_secs_str, SelfProfiler, SelfProfilerRef}; -use rustc_data_structures::sync::{ - AtomicU64, AtomicUsize, Lock, Lrc, OneThread, Ordering, Ordering::SeqCst, -}; +use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; +use rustc_data_structures::sync::{AtomicU64, Lock, Lrc, OneThread, Ordering::SeqCst}; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter; use rustc_errors::emitter::{DynEmitter, EmitterWriter, HumanReadableErrorType}; use rustc_errors::json::JsonEmitter; @@ -46,7 +44,6 @@ use std::ops::{Div, Mul}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::{atomic::AtomicBool, Arc}; -use std::time::Duration; pub struct OptimizationFuel { /// If `-zfuel=crate=n` is specified, initially set to `n`, otherwise `0`. @@ -157,9 +154,6 @@ pub struct Session { /// Used by `-Z self-profile`. pub prof: SelfProfilerRef, - /// Some measurements that are being gathered during compilation. - pub perf_stats: PerfStats, - /// Data about code being compiled, gathered during compilation. pub code_stats: CodeStats, @@ -215,17 +209,6 @@ pub struct Session { pub expanded_args: Vec<String>, } -pub struct PerfStats { - /// The accumulated time spent on computing symbol hashes. - pub symbol_hash_time: Lock<Duration>, - /// Total number of values canonicalized queries constructed. - pub queries_canonicalized: AtomicUsize, - /// Number of times this query is invoked. - pub normalize_generic_arg_after_erasing_regions: AtomicUsize, - /// Number of times this query is invoked. - pub normalize_projection_ty: AtomicUsize, -} - #[derive(PartialEq, Eq, PartialOrd, Ord)] pub enum MetadataKind { None, @@ -883,25 +866,6 @@ impl Session { self.opts.incremental.as_ref().map(|_| self.incr_comp_session_dir()) } - pub fn print_perf_stats(&self) { - eprintln!( - "Total time spent computing symbol hashes: {}", - duration_to_secs_str(*self.perf_stats.symbol_hash_time.lock()) - ); - eprintln!( - "Total queries canonicalized: {}", - self.perf_stats.queries_canonicalized.load(Ordering::Relaxed) - ); - eprintln!( - "normalize_generic_arg_after_erasing_regions: {}", - self.perf_stats.normalize_generic_arg_after_erasing_regions.load(Ordering::Relaxed) - ); - eprintln!( - "normalize_projection_ty: {}", - self.perf_stats.normalize_projection_ty.load(Ordering::Relaxed) - ); - } - /// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n. /// This expends fuel if applicable, and records fuel if applicable. pub fn consider_optimizing( @@ -1515,12 +1479,6 @@ pub fn build_session( io, incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), prof, - perf_stats: PerfStats { - symbol_hash_time: Lock::new(Duration::from_secs(0)), - queries_canonicalized: AtomicUsize::new(0), - normalize_generic_arg_after_erasing_regions: AtomicUsize::new(0), - normalize_projection_ty: AtomicUsize::new(0), - }, code_stats: Default::default(), optimization_fuel, print_fuel, diff --git a/compiler/rustc_session/src/version.rs b/compiler/rustc_session/src/version.rs index 1ad8620bfba..c0c088bcef7 100644 --- a/compiler/rustc_session/src/version.rs +++ b/compiler/rustc_session/src/version.rs @@ -9,7 +9,7 @@ pub struct RustcVersion { } impl RustcVersion { - pub const CURRENT: Self = current_rustc_version!(env!("CFG_RELEASE")); + pub const CURRENT: Self = current_rustc_version!(); } impl Display for RustcVersion { diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 78144524ac5..7cfdbbbf703 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -54,7 +54,7 @@ fn ty_const<'tcx>(constant: &Const, tables: &mut Tables<'tcx>) -> rustc_ty::Cons match constant.internal(tables) { rustc_middle::mir::Const::Ty(c) => c, cnst => { - panic!("Trying to covert constant `{constant:?}` to type constant, but found {cnst:?}") + panic!("Trying to convert constant `{constant:?}` to type constant, but found {cnst:?}") } } } diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 4d2a518226d..f0b368bec39 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -104,6 +104,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::RegionDef(self.create_def_id(did)) } + pub fn coroutine_witness_def(&mut self, did: DefId) -> stable_mir::ty::CoroutineWitnessDef { + stable_mir::ty::CoroutineWitnessDef(self.create_def_id(did)) + } + pub fn prov(&mut self, aid: AllocId) -> stable_mir::ty::Prov { stable_mir::ty::Prov(self.create_alloc_id(aid)) } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 25bd82bf1ef..170f53a7a69 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -455,7 +455,7 @@ impl<'tcx> Stable<'tcx> for mir::BorrowKind { use mir::BorrowKind::*; match *self { Shared => stable_mir::mir::BorrowKind::Shared, - Shallow => stable_mir::mir::BorrowKind::Shallow, + Fake => stable_mir::mir::BorrowKind::Fake, Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) }, } } @@ -1292,7 +1292,11 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { ty::Bound(debruijn_idx, bound_ty) => { TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables)) } - ty::Placeholder(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => { + ty::CoroutineWitness(def_id, args) => TyKind::RigidTy(RigidTy::CoroutineWitness( + tables.coroutine_witness_def(*def_id), + args.stable(tables), + )), + ty::Placeholder(..) | ty::Infer(_) | ty::Error(_) => { unreachable!(); } } @@ -1696,7 +1700,7 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { index: early_reg.index, name: early_reg.name.to_string(), }), - ty::ReLateBound(db_index, bound_reg) => RegionKind::ReLateBound( + ty::ReBound(db_index, bound_reg) => RegionKind::ReBound( db_index.as_u32(), BoundRegion { var: bound_reg.var.as_u32(), kind: bound_reg.kind.stable(tables) }, ), diff --git a/compiler/rustc_span/src/fatal_error.rs b/compiler/rustc_span/src/fatal_error.rs index 8b4f77a0566..26c5711099c 100644 --- a/compiler/rustc_span/src/fatal_error.rs +++ b/compiler/rustc_span/src/fatal_error.rs @@ -3,7 +3,7 @@ #[must_use] pub struct FatalError; -pub struct FatalErrorMarker; +pub use rustc_data_structures::FatalErrorMarker; // Don't implement Send on FatalError. This makes it impossible to `panic_any!(FatalError)`. // We don't want to invoke the panic handler and print a backtrace for fatal errors. diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 36731d0fe74..988ff57254c 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -569,10 +569,6 @@ impl HygieneData { } } -pub fn clear_syntax_context_map() { - HygieneData::with(|data| data.syntax_context_map = FxHashMap::default()); -} - pub fn walk_chain(span: Span, to: SyntaxContext) -> Span { HygieneData::with(|data| data.walk_chain(span, to)) } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index fc13bdff36f..489c8d18926 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -24,6 +24,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(array_windows)] #![feature(cfg_match)] +#![feature(core_io_borrowed_buf)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(min_specialization)] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ff470ce1fa0..302be85a429 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -124,6 +124,7 @@ symbols! { // There is currently no checking that all symbols are used; that would be // nice to have. Symbols { + Abi, AcqRel, Acquire, AddToDiagnostic, @@ -166,6 +167,7 @@ symbols! { CString, Capture, Center, + Cleanup, Clone, Command, ConstParamTy, @@ -194,6 +196,9 @@ symbols! { Error, File, FileType, + Fn, + FnMut, + FnOnce, FormatSpec, Formatter, From, @@ -212,6 +217,7 @@ symbols! { HashSet, Hasher, Implied, + InCleanup, IndexOutput, Input, Instant, @@ -255,6 +261,7 @@ symbols! { NonZeroU8, NonZeroUsize, None, + Normal, Ok, Option, Ord, @@ -1020,6 +1027,36 @@ symbols! { minnumf32, minnumf64, mips_target_feature, + mir_basic_block, + mir_call, + mir_cast_transmute, + mir_checked, + mir_copy_for_deref, + mir_debuginfo, + mir_deinit, + mir_discriminant, + mir_drop, + mir_field, + mir_goto, + mir_len, + mir_make_place, + mir_move, + mir_offset, + mir_retag, + mir_return, + mir_set_discriminant, + mir_static, + mir_static_mut, + mir_storage_dead, + mir_storage_live, + mir_unreachable, + mir_unwind_cleanup, + mir_unwind_continue, + mir_unwind_resume, + mir_unwind_terminate, + mir_unwind_terminate_reason, + mir_unwind_unreachable, + mir_variant, miri, misc, mmx_reg, @@ -1114,6 +1151,7 @@ symbols! { off, offset, offset_of, + offset_of_enum, omit_gdb_pretty_printer_section, on, on_unimplemented, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 53925eeaaa0..0178ff53b24 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -4,7 +4,6 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArg, GenericArgKind}; -use rustc_middle::util::common::record_time; use std::fmt::{self, Write}; use std::mem::{self, discriminant}; @@ -101,40 +100,38 @@ fn get_symbol_hash<'tcx>( tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); - record_time(&tcx.sess.perf_stats.symbol_hash_time, || { - // the main symbol name is not necessarily unique; hash in the - // compiler's internal def-path, guaranteeing each symbol has a - // truly unique path - tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher); - - // Include the main item-type. Note that, in this case, the - // assertions about `has_param` may not hold, but this item-type - // ought to be the same for every reference anyway. - assert!(!item_type.has_erasable_regions()); - hcx.while_hashing_spans(false, |hcx| { - item_type.hash_stable(hcx, &mut hasher); - - // If this is a function, we hash the signature as well. - // This is not *strictly* needed, but it may help in some - // situations, see the `run-make/a-b-a-linker-guard` test. - if let ty::FnDef(..) = item_type.kind() { - item_type.fn_sig(tcx).hash_stable(hcx, &mut hasher); - } + // the main symbol name is not necessarily unique; hash in the + // compiler's internal def-path, guaranteeing each symbol has a + // truly unique path + tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher); + + // Include the main item-type. Note that, in this case, the + // assertions about `has_param` may not hold, but this item-type + // ought to be the same for every reference anyway. + assert!(!item_type.has_erasable_regions()); + hcx.while_hashing_spans(false, |hcx| { + item_type.hash_stable(hcx, &mut hasher); + + // If this is a function, we hash the signature as well. + // This is not *strictly* needed, but it may help in some + // situations, see the `run-make/a-b-a-linker-guard` test. + if let ty::FnDef(..) = item_type.kind() { + item_type.fn_sig(tcx).hash_stable(hcx, &mut hasher); + } - // also include any type parameters (for generic items) - args.hash_stable(hcx, &mut hasher); + // also include any type parameters (for generic items) + args.hash_stable(hcx, &mut hasher); - if let Some(instantiating_crate) = instantiating_crate { - tcx.def_path_hash(instantiating_crate.as_def_id()) - .stable_crate_id() - .hash_stable(hcx, &mut hasher); - } + if let Some(instantiating_crate) = instantiating_crate { + tcx.def_path_hash(instantiating_crate.as_def_id()) + .stable_crate_id() + .hash_stable(hcx, &mut hasher); + } - // We want to avoid accidental collision between different types of instances. - // Especially, `VTableShim`s and `ReifyShim`s may overlap with their original - // instances without this. - discriminant(&instance.def).hash_stable(hcx, &mut hasher); - }); + // We want to avoid accidental collision between different types of instances. + // Especially, `VTableShim`s and `ReifyShim`s may overlap with their original + // instances without this. + discriminant(&instance.def).hash_stable(hcx, &mut hasher); }); // 64 bits should be enough to avoid collisions. diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 5ce188488ce..80dec80bf03 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -270,7 +270,7 @@ fn encode_region<'tcx>( // u6region[I[<region-disambiguator>][<region-index>]E] as vendor extended type let mut s = String::new(); match region.kind() { - RegionKind::ReLateBound(debruijn, r) => { + RegionKind::ReBound(debruijn, r) => { s.push_str("u6regionI"); // Debruijn index, which identifies the binder, as region disambiguator let num = debruijn.index() as u64; @@ -282,6 +282,7 @@ fn encode_region<'tcx>( s.push('E'); compress(dict, DictKey::Region(region), &mut s); } + // FIXME(@lcnr): Why is `ReEarlyBound` reachable here. RegionKind::ReEarlyBound(..) | RegionKind::ReErased => { s.push_str("u6region"); compress(dict, DictKey::Region(region), &mut s); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index ad3d291dfa0..01cbee3a715 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -319,9 +319,9 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { // shorter mangling of `L_`. ty::ReErased => 0, - // Late-bound lifetimes use indices starting at 1, + // Bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. - ty::ReLateBound(debruijn, ty::BoundRegion { var, kind: ty::BrAnon }) => { + ty::ReBound(debruijn, ty::BoundRegion { var, kind: ty::BrAnon }) => { let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let depth = binder.lifetime_depths.start + var.as_u32(); diff --git a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/aarch64_fuchsia.rs deleted file mode 100644 index ddecbb1a8c4..00000000000 --- a/compiler/rustc_target/src/spec/aarch64_fuchsia.rs +++ /dev/null @@ -1 +0,0 @@ -pub use crate::spec::aarch64_unknown_fuchsia::target; diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi/mod.rs index 4c1f0c01a04..4c1f0c01a04 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi/mod.rs diff --git a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs deleted file mode 100644 index 6c16b03cc28..00000000000 --- a/compiler/rustc_target/src/spec/avr_unknown_gnu_atmega328.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::spec::Target; - -pub fn target() -> Target { - super::avr_gnu_base::target("atmega328", "-mmcu=atmega328") -} diff --git a/compiler/rustc_target/src/spec/aix_base.rs b/compiler/rustc_target/src/spec/base/aix.rs index c71c4ba2cc9..c71c4ba2cc9 100644 --- a/compiler/rustc_target/src/spec/aix_base.rs +++ b/compiler/rustc_target/src/spec/base/aix.rs diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/base/android.rs index 9c1df1a0677..af15c16a5a9 100644 --- a/compiler/rustc_target/src/spec/android_base.rs +++ b/compiler/rustc_target/src/spec/base/android.rs @@ -1,7 +1,7 @@ -use crate::spec::{SanitizerSet, TargetOptions}; +use crate::spec::{base, SanitizerSet, TargetOptions}; pub fn opts() -> TargetOptions { - let mut base = super::linux_base::opts(); + let mut base = base::linux::opts(); base.os = "android".into(); base.is_like_android = true; base.default_dwarf_version = 2; diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 7a666eea437..99e64503e25 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -1,10 +1,10 @@ use std::{borrow::Cow, env}; +use crate::spec::{add_link_args, add_link_args_iter}; use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs}; use crate::spec::{LinkerFlavor, Lld, SplitDebuginfo, StaticCow, Target, TargetOptions}; #[cfg(test)] -#[path = "apple/tests.rs"] mod tests; use Arch::*; @@ -102,13 +102,13 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs { LinkerFlavor::Darwin(Cc::No, Lld::No), &["-arch", arch, "-platform_version"], ); - super::add_link_args_iter( + add_link_args_iter( &mut args, LinkerFlavor::Darwin(Cc::No, Lld::No), [platform_name, platform_version.clone(), platform_version].into_iter(), ); if abi != "macabi" { - super::add_link_args(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-arch", arch]); + add_link_args(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-arch", arch]); } args diff --git a/compiler/rustc_target/src/spec/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs index 3b23ddadcc4..f13058ebc82 100644 --- a/compiler/rustc_target/src/spec/apple/tests.rs +++ b/compiler/rustc_target/src/spec/base/apple/tests.rs @@ -1,4 +1,4 @@ -use crate::spec::{ +use crate::spec::targets::{ aarch64_apple_darwin, aarch64_apple_ios_sim, aarch64_apple_watchos_sim, i686_apple_darwin, x86_64_apple_darwin, x86_64_apple_ios, x86_64_apple_tvos, x86_64_apple_watchos_sim, }; diff --git a/compiler/rustc_target/src/spec/avr_gnu_base.rs b/compiler/rustc_target/src/spec/base/avr_gnu.rs index cd324c94bbe..cd324c94bbe 100644 --- a/compiler/rustc_target/src/spec/avr_gnu_base.rs +++ b/compiler/rustc_target/src/spec/base/avr_gnu.rs diff --git a/compiler/rustc_target/src/spec/bpf_base.rs b/compiler/rustc_target/src/spec/base/bpf.rs index 4d03747d016..4d03747d016 100644 --- a/compiler/rustc_target/src/spec/bpf_base.rs +++ b/compiler/rustc_target/src/spec/base/bpf.rs diff --git a/compiler/rustc_target/src/spec/dragonfly_base.rs b/compiler/rustc_target/src/spec/base/dragonfly.rs index de2be781796..de2be781796 100644 --- a/compiler/rustc_target/src/spec/dragonfly_base.rs +++ b/compiler/rustc_target/src/spec/base/dragonfly.rs diff --git a/compiler/rustc_target/src/spec/freebsd_base.rs b/compiler/rustc_target/src/spec/base/freebsd.rs index 8c141aaaec3..8c141aaaec3 100644 --- a/compiler/rustc_target/src/spec/freebsd_base.rs +++ b/compiler/rustc_target/src/spec/base/freebsd.rs diff --git a/compiler/rustc_target/src/spec/fuchsia_base.rs b/compiler/rustc_target/src/spec/base/fuchsia.rs index 4c2775850d1..4c2775850d1 100644 --- a/compiler/rustc_target/src/spec/fuchsia_base.rs +++ b/compiler/rustc_target/src/spec/base/fuchsia.rs diff --git a/compiler/rustc_target/src/spec/haiku_base.rs b/compiler/rustc_target/src/spec/base/haiku.rs index 8ab874410aa..8ab874410aa 100644 --- a/compiler/rustc_target/src/spec/haiku_base.rs +++ b/compiler/rustc_target/src/spec/base/haiku.rs diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/base/hermit.rs index c6e98fc1a11..c6e98fc1a11 100644 --- a/compiler/rustc_target/src/spec/hermit_base.rs +++ b/compiler/rustc_target/src/spec/base/hermit.rs diff --git a/compiler/rustc_target/src/spec/hurd_base.rs b/compiler/rustc_target/src/spec/base/hurd.rs index 76f8223c0e4..76f8223c0e4 100644 --- a/compiler/rustc_target/src/spec/hurd_base.rs +++ b/compiler/rustc_target/src/spec/base/hurd.rs diff --git a/compiler/rustc_target/src/spec/base/hurd_gnu.rs b/compiler/rustc_target/src/spec/base/hurd_gnu.rs new file mode 100644 index 00000000000..3501dbdea1b --- /dev/null +++ b/compiler/rustc_target/src/spec/base/hurd_gnu.rs @@ -0,0 +1,5 @@ +use crate::spec::{base, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { env: "gnu".into(), ..base::hurd::opts() } +} diff --git a/compiler/rustc_target/src/spec/illumos_base.rs b/compiler/rustc_target/src/spec/base/illumos.rs index e63e789752b..e63e789752b 100644 --- a/compiler/rustc_target/src/spec/illumos_base.rs +++ b/compiler/rustc_target/src/spec/base/illumos.rs diff --git a/compiler/rustc_target/src/spec/l4re_base.rs b/compiler/rustc_target/src/spec/base/l4re.rs index 3a4d83fad17..3a4d83fad17 100644 --- a/compiler/rustc_target/src/spec/l4re_base.rs +++ b/compiler/rustc_target/src/spec/base/l4re.rs diff --git a/compiler/rustc_target/src/spec/linux_base.rs b/compiler/rustc_target/src/spec/base/linux.rs index df8e848124a..df8e848124a 100644 --- a/compiler/rustc_target/src/spec/linux_base.rs +++ b/compiler/rustc_target/src/spec/base/linux.rs diff --git a/compiler/rustc_target/src/spec/base/linux_gnu.rs b/compiler/rustc_target/src/spec/base/linux_gnu.rs new file mode 100644 index 00000000000..3491277c440 --- /dev/null +++ b/compiler/rustc_target/src/spec/base/linux_gnu.rs @@ -0,0 +1,5 @@ +use crate::spec::{base, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { env: "gnu".into(), ..base::linux::opts() } +} diff --git a/compiler/rustc_target/src/spec/linux_musl_base.rs b/compiler/rustc_target/src/spec/base/linux_musl.rs index b698bcbcef6..5117cadbee0 100644 --- a/compiler/rustc_target/src/spec/linux_musl_base.rs +++ b/compiler/rustc_target/src/spec/base/linux_musl.rs @@ -1,8 +1,8 @@ use crate::spec::crt_objects; -use crate::spec::{LinkSelfContainedDefault, TargetOptions}; +use crate::spec::{base, LinkSelfContainedDefault, TargetOptions}; pub fn opts() -> TargetOptions { - let mut base = super::linux_base::opts(); + let mut base = base::linux::opts(); base.env = "musl".into(); base.pre_link_objects_self_contained = crt_objects::pre_musl_self_contained(); diff --git a/compiler/rustc_target/src/spec/linux_ohos_base.rs b/compiler/rustc_target/src/spec/base/linux_ohos.rs index 4ad4c837336..273e6a98dd4 100644 --- a/compiler/rustc_target/src/spec/linux_ohos_base.rs +++ b/compiler/rustc_target/src/spec/base/linux_ohos.rs @@ -1,7 +1,7 @@ -use crate::spec::TargetOptions; +use crate::spec::{base, TargetOptions}; pub fn opts() -> TargetOptions { - let mut base = super::linux_base::opts(); + let mut base = base::linux::opts(); base.env = "ohos".into(); base.crt_static_default = false; diff --git a/compiler/rustc_target/src/spec/base/linux_uclibc.rs b/compiler/rustc_target/src/spec/base/linux_uclibc.rs new file mode 100644 index 00000000000..540344e9e94 --- /dev/null +++ b/compiler/rustc_target/src/spec/base/linux_uclibc.rs @@ -0,0 +1,5 @@ +use crate::spec::{base, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { env: "uclibc".into(), ..base::linux::opts() } +} diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs new file mode 100644 index 00000000000..d137aaa5358 --- /dev/null +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -0,0 +1,37 @@ +pub(crate) mod aix; +pub(crate) mod android; +pub(crate) mod apple; +pub(crate) mod avr_gnu; +pub(crate) mod bpf; +pub(crate) mod dragonfly; +pub(crate) mod freebsd; +pub(crate) mod fuchsia; +pub(crate) mod haiku; +pub(crate) mod hermit; +pub(crate) mod hurd; +pub(crate) mod hurd_gnu; +pub(crate) mod illumos; +pub(crate) mod l4re; +pub(crate) mod linux; +pub(crate) mod linux_gnu; +pub(crate) mod linux_musl; +pub(crate) mod linux_ohos; +pub(crate) mod linux_uclibc; +pub(crate) mod msvc; +pub(crate) mod netbsd; +pub(crate) mod nto_qnx; +pub(crate) mod openbsd; +pub(crate) mod redox; +pub(crate) mod solaris; +pub(crate) mod solid; +pub(crate) mod teeos; +pub(crate) mod thumb; +pub(crate) mod uefi_msvc; +pub(crate) mod unikraft_linux_musl; +pub(crate) mod vxworks; +pub(crate) mod wasm; +pub(crate) mod windows_gnu; +pub(crate) mod windows_gnullvm; +pub(crate) mod windows_msvc; +pub(crate) mod windows_uwp_gnu; +pub(crate) mod windows_uwp_msvc; diff --git a/compiler/rustc_target/src/spec/msvc_base.rs b/compiler/rustc_target/src/spec/base/msvc.rs index efe949a4e90..efe949a4e90 100644 --- a/compiler/rustc_target/src/spec/msvc_base.rs +++ b/compiler/rustc_target/src/spec/base/msvc.rs diff --git a/compiler/rustc_target/src/spec/netbsd_base.rs b/compiler/rustc_target/src/spec/base/netbsd.rs index be94ea23465..be94ea23465 100644 --- a/compiler/rustc_target/src/spec/netbsd_base.rs +++ b/compiler/rustc_target/src/spec/base/netbsd.rs diff --git a/compiler/rustc_target/src/spec/nto_qnx_base.rs b/compiler/rustc_target/src/spec/base/nto_qnx.rs index f1405e9b446..f1405e9b446 100644 --- a/compiler/rustc_target/src/spec/nto_qnx_base.rs +++ b/compiler/rustc_target/src/spec/base/nto_qnx.rs diff --git a/compiler/rustc_target/src/spec/openbsd_base.rs b/compiler/rustc_target/src/spec/base/openbsd.rs index e7db14e05a4..e7db14e05a4 100644 --- a/compiler/rustc_target/src/spec/openbsd_base.rs +++ b/compiler/rustc_target/src/spec/base/openbsd.rs diff --git a/compiler/rustc_target/src/spec/redox_base.rs b/compiler/rustc_target/src/spec/base/redox.rs index 468fe478549..468fe478549 100644 --- a/compiler/rustc_target/src/spec/redox_base.rs +++ b/compiler/rustc_target/src/spec/base/redox.rs diff --git a/compiler/rustc_target/src/spec/solaris_base.rs b/compiler/rustc_target/src/spec/base/solaris.rs index f97cdb4fb28..f97cdb4fb28 100644 --- a/compiler/rustc_target/src/spec/solaris_base.rs +++ b/compiler/rustc_target/src/spec/base/solaris.rs diff --git a/compiler/rustc_target/src/spec/solid_base.rs b/compiler/rustc_target/src/spec/base/solid.rs index eaf72b7616c..ce4a8869001 100644 --- a/compiler/rustc_target/src/spec/solid_base.rs +++ b/compiler/rustc_target/src/spec/base/solid.rs @@ -1,5 +1,4 @@ -use super::FramePointer; -use crate::spec::TargetOptions; +use crate::spec::{FramePointer, TargetOptions}; pub fn opts(kernel: &str) -> TargetOptions { TargetOptions { diff --git a/compiler/rustc_target/src/spec/teeos_base.rs b/compiler/rustc_target/src/spec/base/teeos.rs index 1bc71bab016..38d0a6d7314 100644 --- a/compiler/rustc_target/src/spec/teeos_base.rs +++ b/compiler/rustc_target/src/spec/base/teeos.rs @@ -1,12 +1,11 @@ -use super::{Cc, LinkerFlavor, Lld, PanicStrategy}; -use crate::spec::{RelroLevel, TargetOptions}; +use crate::spec::{add_link_args, Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, TargetOptions}; pub fn opts() -> TargetOptions { let lld_args = &["-zmax-page-size=4096", "-znow", "-ztext", "--execute-only"]; let cc_args = &["-Wl,-zmax-page-size=4096", "-Wl,-znow", "-Wl,-ztext", "-mexecute-only"]; let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), lld_args); - super::add_link_args(&mut pre_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), cc_args); + add_link_args(&mut pre_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), cc_args); TargetOptions { os: "teeos".into(), diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/base/thumb.rs index 0decfecb4cd..0decfecb4cd 100644 --- a/compiler/rustc_target/src/spec/thumb_base.rs +++ b/compiler/rustc_target/src/spec/base/thumb.rs diff --git a/compiler/rustc_target/src/spec/uefi_msvc_base.rs b/compiler/rustc_target/src/spec/base/uefi_msvc.rs index a50a55ad7e0..e8acd6078e2 100644 --- a/compiler/rustc_target/src/spec/uefi_msvc_base.rs +++ b/compiler/rustc_target/src/spec/base/uefi_msvc.rs @@ -9,10 +9,10 @@ // the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all // code runs in the same environment, no process separation is supported. -use crate::spec::{LinkerFlavor, Lld, PanicStrategy, StackProbeType, TargetOptions}; +use crate::spec::{base, LinkerFlavor, Lld, PanicStrategy, StackProbeType, TargetOptions}; pub fn opts() -> TargetOptions { - let mut base = super::msvc_base::opts(); + let mut base = base::msvc::opts(); base.add_pre_link_args( LinkerFlavor::Msvc(Lld::No), diff --git a/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs b/compiler/rustc_target/src/spec/base/unikraft_linux_musl.rs index 9ccd0a1e7ca..9ccd0a1e7ca 100644 --- a/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs +++ b/compiler/rustc_target/src/spec/base/unikraft_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/vxworks_base.rs b/compiler/rustc_target/src/spec/base/vxworks.rs index aa4784b63e7..aa4784b63e7 100644 --- a/compiler/rustc_target/src/spec/vxworks_base.rs +++ b/compiler/rustc_target/src/spec/base/vxworks.rs diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/base/wasm.rs index 82a3afeae31..87ade9e58cf 100644 --- a/compiler/rustc_target/src/spec/wasm_base.rs +++ b/compiler/rustc_target/src/spec/base/wasm.rs @@ -1,5 +1,7 @@ -use super::LinkSelfContainedDefault; -use super::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel}; +use crate::spec::{ + add_link_args, cvs, Cc, LinkSelfContainedDefault, LinkerFlavor, PanicStrategy, RelocModel, + TargetOptions, TlsModel, +}; pub fn options() -> TargetOptions { macro_rules! args { @@ -50,7 +52,7 @@ pub fn options() -> TargetOptions { } let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::WasmLld(Cc::No), args!("")); - super::add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,")); + add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,")); TargetOptions { is_like_wasm: true, diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs index b84e0fc0783..25f02dc1451 100644 --- a/compiler/rustc_target/src/spec/windows_gnu_base.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs @@ -1,5 +1,5 @@ -use crate::spec::crt_objects; use crate::spec::LinkSelfContainedDefault; +use crate::spec::{add_link_args, crt_objects}; use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions}; use std::borrow::Cow; @@ -13,7 +13,7 @@ pub fn opts() -> TargetOptions { "--disable-auto-image-base", ], ); - super::add_link_args( + add_link_args( &mut pre_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[ @@ -45,14 +45,14 @@ pub fn opts() -> TargetOptions { ]; let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs); - super::add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs); + add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs); // If any of our crates are dynamically linked then we need to use // the shared libgcc_s-dw2-1.dll. This is required to support // unwinding across DLL boundaries. let dynamic_unwind_libs = &["-lgcc_s"]; let mut late_link_args_dynamic = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), dynamic_unwind_libs); - super::add_link_args( + add_link_args( &mut late_link_args_dynamic, LinkerFlavor::Gnu(Cc::Yes, Lld::No), dynamic_unwind_libs, @@ -65,7 +65,7 @@ pub fn opts() -> TargetOptions { let static_unwind_libs = &["-lgcc_eh", "-l:libpthread.a"]; let mut late_link_args_static = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), static_unwind_libs); - super::add_link_args( + add_link_args( &mut late_link_args_static, LinkerFlavor::Gnu(Cc::Yes, Lld::No), static_unwind_libs, diff --git a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs index b1d8e2be5a6..b1d8e2be5a6 100644 --- a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs diff --git a/compiler/rustc_target/src/spec/windows_msvc_base.rs b/compiler/rustc_target/src/spec/base/windows_msvc.rs index 21062c337d8..e3cf9757219 100644 --- a/compiler/rustc_target/src/spec/windows_msvc_base.rs +++ b/compiler/rustc_target/src/spec/base/windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::{cvs, TargetOptions}; +use crate::spec::{base, cvs, TargetOptions}; pub fn opts() -> TargetOptions { - let base = super::msvc_base::opts(); + let base = base::msvc::opts(); TargetOptions { os: "windows".into(), diff --git a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs b/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs index f30c33d997e..17256e18e24 100644 --- a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs +++ b/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkArgs, LinkerFlavor, Lld, TargetOptions}; +use crate::spec::{add_link_args, base, Cc, LinkArgs, LinkerFlavor, Lld, TargetOptions}; pub fn opts() -> TargetOptions { - let base = super::windows_gnu_base::opts(); + let base = base::windows_gnu::opts(); // FIXME: This should be updated for the exception machinery changes from #67502 // and inherit from `windows_gnu_base`, at least partially. @@ -17,7 +17,7 @@ pub fn opts() -> TargetOptions { ]; let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs); - super::add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs); + add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs); // Reset the flags back to empty until the FIXME above is addressed. let late_link_args_dynamic = LinkArgs::new(); let late_link_args_static = LinkArgs::new(); diff --git a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs b/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs index 8c942c59dd0..59a76167125 100644 --- a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs +++ b/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::{LinkerFlavor, Lld, TargetOptions}; +use crate::spec::{base, LinkerFlavor, Lld, TargetOptions}; pub fn opts() -> TargetOptions { - let mut opts = super::windows_msvc_base::opts(); + let mut opts = base::windows_msvc::opts(); opts.abi = "uwp".into(); opts.vendor = "uwp".into(); diff --git a/compiler/rustc_target/src/spec/hurd_gnu_base.rs b/compiler/rustc_target/src/spec/hurd_gnu_base.rs deleted file mode 100644 index b9cf26d9380..00000000000 --- a/compiler/rustc_target/src/spec/hurd_gnu_base.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::spec::TargetOptions; - -pub fn opts() -> TargetOptions { - TargetOptions { env: "gnu".into(), ..super::hurd_base::opts() } -} diff --git a/compiler/rustc_target/src/spec/linux_gnu_base.rs b/compiler/rustc_target/src/spec/linux_gnu_base.rs deleted file mode 100644 index 8d6b3f18512..00000000000 --- a/compiler/rustc_target/src/spec/linux_gnu_base.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::spec::TargetOptions; - -pub fn opts() -> TargetOptions { - TargetOptions { env: "gnu".into(), ..super::linux_base::opts() } -} diff --git a/compiler/rustc_target/src/spec/linux_uclibc_base.rs b/compiler/rustc_target/src/spec/linux_uclibc_base.rs deleted file mode 100644 index 4ba480ffecf..00000000000 --- a/compiler/rustc_target/src/spec/linux_uclibc_base.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::spec::TargetOptions; - -pub fn opts() -> TargetOptions { - TargetOptions { env: "uclibc".into(), ..super::linux_base::opts() } -} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 48ca5fcf3ad..d8dd4ae2286 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -57,47 +57,11 @@ use rustc_macros::HashStable_Generic; pub mod abi; pub mod crt_objects; -mod aix_base; -mod android_base; -mod apple_base; -pub use apple_base::deployment_target as current_apple_deployment_target; -pub use apple_base::platform as current_apple_platform; -pub use apple_base::sdk_version as current_apple_sdk_version; -mod avr_gnu_base; -pub use avr_gnu_base::ef_avr_arch; -mod bpf_base; -mod dragonfly_base; -mod freebsd_base; -mod fuchsia_base; -mod haiku_base; -mod hermit_base; -mod hurd_base; -mod hurd_gnu_base; -mod illumos_base; -mod l4re_base; -mod linux_base; -mod linux_gnu_base; -mod linux_musl_base; -mod linux_ohos_base; -mod linux_uclibc_base; -mod msvc_base; -mod netbsd_base; -mod nto_qnx_base; -mod openbsd_base; -mod redox_base; -mod solaris_base; -mod solid_base; -mod teeos_base; -mod thumb_base; -mod uefi_msvc_base; -mod unikraft_linux_musl_base; -mod vxworks_base; -mod wasm_base; -mod windows_gnu_base; -mod windows_gnullvm_base; -mod windows_msvc_base; -mod windows_uwp_gnu_base; -mod windows_uwp_msvc_base; +mod base; +pub use base::apple::deployment_target as current_apple_deployment_target; +pub use base::apple::platform as current_apple_platform; +pub use base::apple::sdk_version as current_apple_sdk_version; +pub use base::avr_gnu::ef_avr_arch; /// Linker is called through a C/C++ compiler. #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] @@ -1444,14 +1408,16 @@ impl fmt::Display for StackProtector { macro_rules! supported_targets { ( $(($triple:literal, $module:ident),)+ ) => { - $(mod $module;)+ + mod targets { + $(pub(crate) mod $module;)+ + } /// List of supported targets pub const TARGETS: &[&str] = &[$($triple),+]; fn load_builtin(target: &str) -> Option<Target> { let mut t = match target { - $( $triple => $module::target(), )+ + $( $triple => targets::$module::target(), )+ _ => return None, }; t.is_builtin = true; @@ -1467,7 +1433,7 @@ macro_rules! supported_targets { $( #[test] // `#[test]` fn $module() { - tests_impl::test_target(super::$module::target()); + tests_impl::test_target(crate::spec::targets::$module::target()); } )+ } @@ -3537,7 +3503,7 @@ impl TargetTriple { /// If this target is a path, a hash of the path is appended to the triple returned /// by `triple()`. pub fn debug_triple(&self) -> String { - use std::collections::hash_map::DefaultHasher; + use std::hash::DefaultHasher; match self { TargetTriple::TargetTriple(triple) => triple.to_owned(), diff --git a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs index 9ac73235141..8e6c00b1255 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs @@ -1,4 +1,4 @@ -use super::apple_base::{macos_llvm_target, opts, Arch}; +use crate::spec::base::apple::{macos_llvm_target, opts, Arch}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs index e9edfd2877b..9fc5b5de466 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_base::{ios_llvm_target, opts, Arch}; +use crate::spec::base::apple::{ios_llvm_target, opts, Arch}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs index b29ab14e7f2..0172a3a9c2e 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, Arch}; +use crate::spec::base::apple::{opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs index 6e2d62b6e08..602a687779e 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs @@ -1,4 +1,4 @@ -use super::apple_base::{ios_sim_llvm_target, opts, Arch}; +use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs index f7cdfa71c4b..a1a31935509 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, tvos_llvm_target, Arch}; +use crate::spec::base::apple::{opts, tvos_llvm_target, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs index 909a52a5097..7b0bbb28e47 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_tvos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, tvos_sim_llvm_target, Arch}; +use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs index e4af4127c22..014560d2278 100644 --- a/compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, watchos_sim_llvm_target, Arch}; +use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch}; use crate::spec::{FramePointer, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs index b84783c0a40..bbaa870ec2e 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { max_atomic_width: Some(128), mcount: "\u{1}_mcount".into(), endian: Endian::Big, - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs index a24e0119f25..7536e507b3d 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.max_atomic_width = Some(128); Target { diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs index 98ae05974aa..21de8a71a0d 100644 --- a/compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -11,7 +11,7 @@ pub fn target() -> Target { mcount: "__mcount".into(), max_atomic_width: Some(128), endian: Endian::Big, - ..super::netbsd_base::opts() + ..base::netbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs new file mode 100644 index 00000000000..3668db912bb --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs @@ -0,0 +1 @@ +pub use crate::spec::targets::aarch64_unknown_fuchsia::target; diff --git a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs index 437fd601580..e5e22fd1ee2 100644 --- a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs @@ -1,7 +1,7 @@ -use super::{RelocModel, Target, TargetOptions}; +use crate::spec::{base, RelocModel, Target, TargetOptions}; pub fn target() -> Target { - let base = super::solid_base::opts("asp3"); + let base = base::solid::opts("asp3"); Target { llvm_target: "aarch64-unknown-none".into(), pointer_width: 64, diff --git a/compiler/rustc_target/src/spec/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs index 071b727b35c..7c6fed7ab99 100644 --- a/compiler/rustc_target/src/spec/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs @@ -1,4 +1,4 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; // See https://developer.android.com/ndk/guides/abis.html#arm64-v8a // for target ABI requirements. @@ -20,7 +20,7 @@ pub fn target() -> Target { | SanitizerSet::SHADOWCALLSTACK | SanitizerSet::ADDRESS, supports_xray: true, - ..super::android_base::opts() + ..base::android::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs index e271bdc8a01..02fcc2bb43e 100644 --- a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs @@ -1,4 +1,4 @@ -use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, Target, TargetOptions}; +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, Target, TargetOptions}; const LINKER_SCRIPT: &str = include_str!("./aarch64_nintendo_switch_freestanding_linker_script.ld"); diff --git a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding_linker_script.ld b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding_linker_script.ld index f3441e65937..f3441e65937 100644 --- a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding_linker_script.ld +++ b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding_linker_script.ld diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs index cf1d7ca1158..1ea73814282 100644 --- a/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_gnullvm_base::opts(); + let mut base = base::windows_gnullvm::opts(); base.max_atomic_width = Some(128); base.features = "+v8a,+neon,+fp-armv8".into(); base.linker = Some("aarch64-w64-mingw32-clang".into()); diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index 56b76bc7ada..cbd1329726a 100644 --- a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_msvc_base::opts(); + let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); base.features = "+v8a,+neon,+fp-armv8".into(); diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs index 84fa9814bbe..0f95984a31f 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { | SanitizerSet::CFI | SanitizerSet::MEMORY | SanitizerSet::THREAD, - ..super::freebsd_base::opts() + ..base::freebsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs index a5683fa7348..cacc6ea235a 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs @@ -1,4 +1,4 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::SHADOWCALLSTACK, - ..super::fuchsia_base::opts() + ..base::fuchsia::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs index 2414867be55..3839e0b9c46 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -9,7 +9,7 @@ pub fn target() -> Target { options: TargetOptions { features: "+v8a,+strict-align,+neon,+fp-armv8".into(), max_atomic_width: Some(128), - ..super::hermit_base::opts() + ..base::hermit::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs index da246089440..c0b07db3818 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -18,7 +18,7 @@ pub fn target() -> Target { | SanitizerSet::THREAD | SanitizerSet::HWADDRESS, supports_xray: true, - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs index ad9df53c2b7..d4c6271b241 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -11,7 +11,7 @@ pub fn target() -> Target { features: "+v8a,+outline-atomics".into(), max_atomic_width: Some(128), mcount: "\u{1}_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs index 523eb6bd2fe..364df677e44 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.max_atomic_width = Some(128); base.supports_xray = true; base.features = "+v8a".into(); diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs index c8f3db00e01..5f3bef63aa6 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs @@ -1,9 +1,8 @@ -use crate::spec::{Target, TargetOptions}; - -use super::SanitizerSet; +use crate::spec::SanitizerSet; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_ohos_base::opts(); + let mut base = base::linux_ohos::opts(); base.max_atomic_width = Some(128); Target { diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs index a58b64d3d03..3194d16ff47 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -10,7 +10,7 @@ pub fn target() -> Target { features: "+v8a".into(), mcount: "__mcount".into(), max_atomic_width: Some(128), - ..super::netbsd_base::opts() + ..base::netbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs index be27302f7f5..88fa6d5a762 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs @@ -6,7 +6,7 @@ // // For example, `-C target-cpu=cortex-a53`. -use super::{ +use crate::spec::{ Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target, TargetOptions, }; diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs index 9dfa1f268ac..48b79b0b9ba 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs @@ -6,7 +6,7 @@ // // For example, `-C target-cpu=cortex-a53`. -use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Target { let opts = TargetOptions { diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx_710.rs index 630642dcd33..aeeaab3af32 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx_710.rs @@ -1,5 +1,4 @@ -use super::nto_qnx_base; -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -24,7 +23,7 @@ pub fn target() -> Target { &["-Vgcc_ntoaarch64le_cxx"], ), env: "nto71".into(), - ..nto_qnx_base::opts() + ..base::nto_qnx::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs index 224e31af24f..e3f5aafc7d4 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -9,7 +9,7 @@ pub fn target() -> Target { options: TargetOptions { features: "+v8a".into(), max_atomic_width: Some(128), - ..super::openbsd_base::opts() + ..base::openbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs index 5650162cdbc..de875e29ffd 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::redox_base::opts(); + let mut base = base::redox::opts(); base.max_atomic_width = Some(128); base.features = "+v8a".into(); diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs index 64a7dc681c8..eec2668d487 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::teeos_base::opts(); + let mut base = base::teeos::opts(); base.features = "+strict-align,+neon,+fp-armv8".into(); base.max_atomic_width = Some(128); base.linker = Some("aarch64-linux-gnu-ld".into()); diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs index 82fb015569d..9ed6ed2651f 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs @@ -1,11 +1,10 @@ // This defines the aarch64 target for UEFI systems as described in the UEFI specification. See the // uefi-base module for generic UEFI options. -use super::uefi_msvc_base; -use crate::spec::{LinkerFlavor, Lld, Target}; +use crate::spec::{base, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = uefi_msvc_base::opts(); + let mut base = base::uefi_msvc::opts(); base.max_atomic_width = Some(128); base.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/machine:arm64"]); diff --git a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs index d39442d9177..c64b2c7d113 100644 --- a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_uwp_msvc_base::opts(); + let mut base = base::windows_uwp_msvc::opts(); base.max_atomic_width = Some(128); base.features = "+v8a".into(); diff --git a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs index 7e2af4c7a6a..29f61d85778 100644 --- a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -9,7 +9,7 @@ pub fn target() -> Target { options: TargetOptions { features: "+v8a".into(), max_atomic_width: Some(128), - ..super::vxworks_base::opts() + ..base::vxworks::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs index c757ed45e47..9931b7b866c 100644 --- a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, Arch}; +use crate::spec::base::apple::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/arm_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs index bbf1fa315ab..43b27b414d8 100644 --- a/compiler/rustc_target/src/spec/arm_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+strict-align,+v5te".into(), supported_sanitizers: SanitizerSet::ADDRESS, max_atomic_width: Some(32), - ..super::android_base::opts() + ..base::android::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs index 400030ca0c6..e4fa54c4b75 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs index 6228fb15a83..f379ea35ecb 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs index 3ef441d6a60..f3d5ff89244 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -16,7 +16,7 @@ pub fn target() -> Target { features: "+strict-align,+v6".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs index eb6660d4c28..f3e366d5993 100644 --- a/compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -16,7 +16,7 @@ pub fn target() -> Target { features: "+strict-align,+v6,+vfp2,-d32".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs index 1d66515a72e..07c7e1c5845 100644 --- a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs index 446efa90d09..446efa90d09 100644 --- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs index 0c9e99ff84b..0c9e99ff84b 100644 --- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs diff --git a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs index 44fdd3178af..44fdd3178af 100644 --- a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs index cffebcc9581..5ab753c3d61 100644 --- a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), has_thumb_interworking: true, - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs index dfd27b65474..5e23efecdbe 100644 --- a/compiler/rustc_target/src/spec/armv5te_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs @@ -1,6 +1,6 @@ //! Targets the ARMv5TE, with code as `a32` code by default. -use crate::spec::{cvs, FramePointer, Target, TargetOptions}; +use crate::spec::{base, cvs, FramePointer, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -35,7 +35,7 @@ pub fn target() -> Target { atomic_cas: false, has_thumb_interworking: true, - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs index b940563102b..7155ab289c0 100644 --- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "\u{1}__gnu_mcount_nc".into(), has_thumb_interworking: true, - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs index 2530971b502..3f25ab2bcc1 100644 --- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -17,7 +17,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "\u{1}mcount".into(), has_thumb_interworking: true, - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs index a51be10a3d8..af6e3baa27a 100644 --- a/compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "\u{1}__gnu_mcount_nc".into(), has_thumb_interworking: true, - ..super::linux_uclibc_base::opts() + ..base::linux_uclibc::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs index 4a8aa31576f..22f6ee81055 100644 --- a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), - ..super::freebsd_base::opts() + ..base::freebsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs index 6e26f686fcb..84d9ceac04d 100644 --- a/compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { features: "+v6,+vfp2,-d32".into(), max_atomic_width: Some(64), mcount: "__mcount".into(), - ..super::netbsd_base::opts() + ..base::netbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs index 23f4a5abf77..23f4a5abf77 100644 --- a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs +++ b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs diff --git a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs index 402e0fd9236..bb3e574e32f 100644 --- a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; // This target if is for the baseline of the Android v7a ABI // in thumb mode. It's named armv7-* instead of thumbv7-* @@ -9,7 +9,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; // for target ABI requirements. pub fn target() -> Target { - let mut base = super::android_base::opts(); + let mut base = base::android::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]); Target { llvm_target: "armv7-none-linux-android".into(), diff --git a/compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs index 62c93603621..62c93603621 100644 --- a/compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs diff --git a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs index bc37b62de8e..9f4a432c6fa 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), - ..super::freebsd_base::opts() + ..base::freebsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs index 73ae212a7a6..ad9fd773b8b 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for glibc Linux on ARMv7 without thumb-mode, NEON or // hardfloat. @@ -15,7 +15,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs index e39ea49a003..aad7977d504 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for glibc Linux on ARMv7 without NEON or // thumb-mode. See the thumbv7neon variant for enabling both. @@ -15,7 +15,7 @@ pub fn target() -> Target { features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}__gnu_mcount_nc".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs index 7dae8577396..7f30a5ad7d7 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for musl Linux on ARMv7 without thumb-mode, NEON or // hardfloat. @@ -20,7 +20,7 @@ pub fn target() -> Target { features: "+v7,+thumb2,+soft-float,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs index ba83964bf58..ec5c6419f63 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for musl Linux on ARMv7 without thumb-mode or NEON. @@ -19,7 +19,7 @@ pub fn target() -> Target { features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs index e9b0bda68ef..9f2ac541ddc 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for OpenHarmony on ARMv7 Linux with thumb-mode, but no NEON or // hardfloat. @@ -18,7 +18,7 @@ pub fn target() -> Target { features: "+v7,+thumb2,+soft-float,-neon".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_ohos_base::opts() + ..base::linux_ohos::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs index 171f67070d5..212c80718f0 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs @@ -1,10 +1,10 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for uclibc Linux on ARMv7 without NEON, // thumb-mode or hardfloat. pub fn target() -> Target { - let base = super::linux_uclibc_base::opts(); + let base = base::linux_uclibc::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabi".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs index d3e95a6573d..f760ad9e79c 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs @@ -1,10 +1,10 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for uclibc Linux on ARMv7 without NEON or // thumb-mode. See the thumbv7neon variant for enabling both. pub fn target() -> Target { - let base = super::linux_uclibc_base::opts(); + let base = base::linux_uclibc::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabihf".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs index c89ae248398..e5518c6daec 100644 --- a/compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), mcount: "__mcount".into(), - ..super::netbsd_base::opts() + ..base::netbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs index c1ab90172e2..0b4e64307d2 100644 --- a/compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -11,7 +11,7 @@ pub fn target() -> Target { // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+vfp3,-d32,+thumb2,-neon".into(), max_atomic_width: Some(64), - ..super::vxworks_base::opts() + ..base::vxworks::opts() }, } } diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs index b49dc650bd0..57d40d54c44 100644 --- a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs @@ -1,7 +1,7 @@ -use super::{RelocModel, Target, TargetOptions}; +use crate::spec::{base, RelocModel, Target, TargetOptions}; pub fn target() -> Target { - let base = super::solid_base::opts("asp3"); + let base = base::solid::opts("asp3"); Target { llvm_target: "armv7a-none-eabi".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs index 7d30238e8ab..3d21213c5ff 100644 --- a/compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs @@ -1,7 +1,7 @@ -use super::{RelocModel, Target, TargetOptions}; +use crate::spec::{base, RelocModel, Target, TargetOptions}; pub fn target() -> Target { - let base = super::solid_base::opts("asp3"); + let base = base::solid::opts("asp3"); Target { llvm_target: "armv7a-none-eabihf".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs index d59de86a230..c5b61427e69 100644 --- a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs @@ -14,7 +14,7 @@ // - `relocation-model` set to `static`; also no PIE, no relro and no dynamic // linking. rationale: matches `thumb` targets -use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Target { let opts = TargetOptions { diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs index c134f3e0907..ba3caad6a97 100644 --- a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs @@ -5,7 +5,7 @@ // changes (list in `armv7a_none_eabi.rs`) to bring it closer to the bare-metal // `thumb` & `aarch64` targets. -use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Target { let opts = TargetOptions { diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs index 6e1d00d1f6c..751fdcb20f1 100644 --- a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, Arch}; +use crate::spec::base::apple::{opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs index 68b2527985a..68b2527985a 100644 --- a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs index 909765a310f..909765a310f 100644 --- a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs diff --git a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs index be7f8542c9e..44c624c4ebd 100644 --- a/compiler/rustc_target/src/spec/armv7s_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_base::{ios_llvm_target, opts, Arch}; +use crate::spec::base::apple::{ios_llvm_target, opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs index f492c3451a4..e4768c67af5 100644 --- a/compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs @@ -1,4 +1,4 @@ -use super::{wasm32_unknown_emscripten, LinkerFlavor, Target}; +use crate::spec::{targets::wasm32_unknown_emscripten, LinkerFlavor, Target}; pub fn target() -> Target { let mut target = wasm32_unknown_emscripten::target(); diff --git a/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs new file mode 100644 index 00000000000..bf01413a80a --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs @@ -0,0 +1,5 @@ +use crate::spec::{base, Target}; + +pub fn target() -> Target { + base::avr_gnu::target("atmega328", "-mmcu=atmega328") +} diff --git a/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs index 174ddfa50bf..91e091e237a 100644 --- a/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs @@ -1,5 +1,5 @@ use crate::spec::Target; -use crate::{abi::Endian, spec::bpf_base}; +use crate::{abi::Endian, spec::base}; pub fn target() -> Target { Target { @@ -7,6 +7,6 @@ pub fn target() -> Target { data_layout: "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), pointer_width: 64, arch: "bpf".into(), - options: bpf_base::opts(Endian::Big), + options: base::bpf::opts(Endian::Big), } } diff --git a/compiler/rustc_target/src/spec/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs index 7625e7b0e48..45ab750ead6 100644 --- a/compiler/rustc_target/src/spec/bpfel_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs @@ -1,5 +1,5 @@ use crate::spec::Target; -use crate::{abi::Endian, spec::bpf_base}; +use crate::{abi::Endian, spec::base}; pub fn target() -> Target { Target { @@ -7,6 +7,6 @@ pub fn target() -> Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), pointer_width: 64, arch: "bpf".into(), - options: bpf_base::opts(Endian::Little), + options: base::bpf::opts(Endian::Little), } } diff --git a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs index 93becd70869..14cd33a260a 100644 --- a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs +++ b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs @@ -1,4 +1,4 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; // This target is for glibc Linux on Csky @@ -14,7 +14,7 @@ pub fn target() -> Target { features: "+2e3,+3e7,+7e10,+cache,+dsp1e2,+dspe60,+e1,+e2,+edsp,+elrw,+hard-tp,+high-registers,+hwdiv,+mp,+mp1e2,+nvic,+trust".into(), late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-l:libatomic.a"]), max_atomic_width: Some(32), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2hf.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs index 74518834160..0ce271c601c 100644 --- a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2hf.rs +++ b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; // This target is for glibc Linux on Csky @@ -15,7 +15,7 @@ pub fn target() -> Target { features: "+hard-float,+hard-float-abi,+2e3,+3e7,+7e10,+cache,+dsp1e2,+dspe60,+e1,+e2,+edsp,+elrw,+hard-tp,+high-registers,+hwdiv,+mp,+mp1e2,+nvic,+trust".into(), late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-l:libatomic.a", "-mhard-float"]), max_atomic_width: Some(32), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs index 4c6ab5f5ae4..98a5e7abd09 100644 --- a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "hexagonv60".into(); base.max_atomic_width = Some(32); // FIXME: HVX length defaults are per-CPU diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs index 5819981612e..ed2c990ffa6 100644 --- a/compiler/rustc_target/src/spec/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_base::{ios_sim_llvm_target, opts, Arch}; +use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i386_unknown_linux_gnu.rs index 801a8893399..801a8893399 100644 --- a/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i386_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i486_unknown_linux_gnu.rs index a11fbecc3c3..a11fbecc3c3 100644 --- a/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i486_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs index 68afa7fe401..06089391623 100644 --- a/compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs @@ -1,5 +1,4 @@ -use super::nto_qnx_base; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -18,7 +17,7 @@ pub fn target() -> Target { ), env: "nto70".into(), stack_probes: StackProbeType::X86, - ..nto_qnx_base::opts() + ..base::nto_qnx::opts() }, } } diff --git a/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs index befb0f89f3b..befb0f89f3b 100644 --- a/compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs diff --git a/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs index b699a7af177..b699a7af177 100644 --- a/compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs diff --git a/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs index 55a26eb004a..55a26eb004a 100644 --- a/compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/i586_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs index 0d8bdc3f89f..8375fa4c0c0 100644 --- a/compiler/rustc_target/src/spec/i586_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{StackProbeType, Target, TargetOptions}; +use crate::spec::{base, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.cpu = "pentium".into(); base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::Call; diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index b5103d15db6..242fe5ed98a 100644 --- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -1,4 +1,4 @@ -use super::apple_base::{macos_llvm_target, opts, Arch}; +use crate::spec::base::apple::{macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs index c7c30c23901..987265598eb 100644 --- a/compiler/rustc_target/src/spec/i686_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs @@ -1,10 +1,10 @@ -use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions}; // See https://developer.android.com/ndk/guides/abis.html#x86 // for target ABI requirements. pub fn target() -> Target { - let mut base = super::android_base::opts(); + let mut base = base::android::opts(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs index 7a11138754f..8d4a39b5811 100644 --- a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_gnu_base::opts(); + let mut base = base::windows_gnu::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.frame_pointer = FramePointer::Always; // Required for backtraces diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs index 3154b512a52..bb410cd8caf 100644 --- a/compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_gnullvm_base::opts(); + let mut base = base::windows_gnullvm::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.frame_pointer = FramePointer::Always; // Required for backtraces diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs index db4c00dc697..ba80c23196e 100644 --- a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::{LinkerFlavor, Lld, Target}; +use crate::spec::{base, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_msvc_base::opts(); + let mut base = base::windows_msvc::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs index 35ca78034f1..70aa0b47962 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::freebsd_base::opts(); + let mut base = base::freebsd::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-znotext"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs index e6b72336c5c..9715f6c21d9 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::haiku_base::opts(); + let mut base = base::haiku::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs index 29f80360138..9102673ef77 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::hurd_gnu_base::opts(); + let mut base = base::hurd_gnu::opts(); base.cpu = "pentiumpro".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs index 73e536a7e4d..0ca058b2fd2 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.supported_sanitizers = SanitizerSet::ADDRESS; diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs index 3825082ba25..ce0df3a7234 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-melf_i386"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs index b191996c7de..2a3ac5932d3 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs index 8babe559712..45883542bea 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::openbsd_base::opts(); + let mut base = base::openbsd::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-fuse-ld=lld"]); diff --git a/compiler/rustc_target/src/spec/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs index a2e42c5e61d..25315e19cdd 100644 --- a/compiler/rustc_target/src/spec/i686_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs @@ -5,10 +5,10 @@ // The cdecl ABI is used. It differs from the stdcall or fastcall ABI. // "i686-unknown-windows" is used to get the minimal subset of windows-specific features. -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::uefi_msvc_base::opts(); + let mut base = base::uefi_msvc::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs index a3e32569827..ec211a710eb 100644 --- a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_uwp_gnu_base::opts(); + let mut base = base::windows_uwp_gnu::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.frame_pointer = FramePointer::Always; // Required for backtraces diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs index 4c657fe908a..7cca2fc6b9f 100644 --- a/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_uwp_msvc_base::opts(); + let mut base = base::windows_uwp_msvc::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs index b5cfdfcebea..965a895972c 100644 --- a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::vxworks_base::opts(); + let mut base = base::vxworks::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs index db8b9c70e67..0f05e7c475a 100644 --- a/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -11,7 +11,7 @@ pub fn target() -> Target { features: "+f,+d".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs index dbc96d68eae..3b1ea8e206f 100644 --- a/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs @@ -1,5 +1,5 @@ -use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel}; -use super::{Target, TargetOptions}; +use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { Target { diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs index c4d5c7bc44c..ab9300ef9c7 100644 --- a/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs @@ -1,5 +1,5 @@ -use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel}; -use super::{Target, TargetOptions}; +use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel}; +use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { Target { diff --git a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs index 9bcd56bed00..b54f5d753cc 100644 --- a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "M68020".into(); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs index 3c6ef52c6cd..6191a6dfd41 100644 --- a/compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs @@ -1,10 +1,10 @@ /// A target tuple for OpenWrt MIPS64 targets /// use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "mips64r2".into(); base.features = "+mips64r2,+soft-float".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs index b9df0046b12..e1131f07f26 100644 --- a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -16,7 +16,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs index 465e97a026c..147c1c22476 100644 --- a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "mips64r2".into(); base.features = "+mips64r2".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs index 57ad8c47399..4c612554d20 100644 --- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs index 75575eb7eeb..d60404f0ce5 100644 --- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs @@ -1,7 +1,7 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "mips64r2".into(); base.features = "+mips64r2".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs index 8df8b0b4c2c..c49b89bbd46 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs index c2846313a9e..92d2d9d84c1 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "mips32r2".into(); base.features = "+mips32r2,+soft-float".into(); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs index c59bb5fdd22..51df0a974cb 100644 --- a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_uclibc_base::opts() + ..base::linux_uclibc::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs index 75beb91b13a..75beb91b13a 100644 --- a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psp_linker_script.ld b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp_linker_script.ld index 9eb35ad9f5d..9eb35ad9f5d 100644 --- a/compiler/rustc_target/src/spec/mipsel_sony_psp_linker_script.ld +++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp_linker_script.ld diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psx.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs index 12a66efdd46..12a66efdd46 100644 --- a/compiler/rustc_target/src/spec/mipsel_sony_psx.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs index 01346e71a92..c2e482148cd 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs index 0e8f1a2c8e0..5eed050453d 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "mips32r2".into(); base.features = "+mips32r2,+soft-float".into(); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs index 8342074586b..77e69119d16 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_uclibc_base::opts() + ..base::linux_uclibc::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs index 651358d6422..706a1af3e15 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.max_atomic_width = Some(32); base.cpu = "mips32".into(); diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs index 43b01e7a062..43b01e7a062 100644 --- a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs diff --git a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs index 983a449b006..59783882e18 100644 --- a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs index ec0facdfb7b..c3d79412e1c 100644 --- a/compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { max_atomic_width: Some(32), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs index 16dd1c416f4..2ae6e7521f9 100644 --- a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -16,7 +16,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs index 8d0a6aa8f51..31637e9f6d0 100644 --- a/compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), mcount: "_mcount".into(), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/msp430_none_elf.rs b/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs index 251fd2a0a7a..251fd2a0a7a 100644 --- a/compiler/rustc_target/src/spec/msp430_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs index b0582b235b9..b0582b235b9 100644 --- a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs +++ b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs diff --git a/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs index 4e105a03e28..c512e4c7c48 100644 --- a/compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut base = super::aix_base::opts(); + let mut base = base::aix::opts(); base.max_atomic_width = Some(64); base.add_pre_link_args( LinkerFlavor::Unix(Cc::No), diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs index e8fe55a00db..e470ec05eff 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::freebsd_base::opts(); + let mut base = base::freebsd::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs index 7a0cc539f1a..34e3184d348 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs index f80b22828c1..e2e707f4a1a 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs index 3643f7b0c37..ebaeb04be31 100644 --- a/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::openbsd_base::opts(); + let mut base = base::openbsd::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs index b0472e64e13..e2085ba7ce3 100644 --- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::vxworks_base::opts(); + let mut base = base::vxworks::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs index 342b1cf4f4c..b399d36d8b2 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::freebsd_base::opts(); + let mut base = base::freebsd::opts(); base.cpu = "ppc64le".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs index 815e3d2781c..194c3170e68 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "ppc64le".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs index 0b9b78bcec8..1f53e689598 100644 --- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "ppc64le".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs index e036f5bdbad..6d094f9a367 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::freebsd_base::opts(); + let mut base = base::freebsd::opts(); // Extra hint to linker that we are generating secure-PLT code. base.add_pre_link_args( LinkerFlavor::Gnu(Cc::Yes, Lld::No), diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs index c8d6f8b9c67..1600698da44 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs index fdaa9d366d9..af0fbfebef2 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs index 7fe708cf530..9b0ac4a0fc9 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs index 6f8875ba7b4..bc2e239d9a5 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs index 280d36698b4..081aaaea249 100644 --- a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{StackProbeType, Target}; +use crate::spec::{base, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::openbsd_base::opts(); + let mut base = base::openbsd::opts(); base.endian = Endian::Big; base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs index 6f245e6ab62..e8bccc15385 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::vxworks_base::opts(); + let mut base = base::vxworks::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "--secure-plt"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs index 1d5a5e5c6ac..fa4ef098e03 100644 --- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::vxworks_base::opts(); + let mut base = base::vxworks::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe", "--secure-plt"]); base.max_atomic_width = Some(32); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs index bffd377bc4a..06e8f183763 100644 --- a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "ilp32d".into(), max_atomic_width: Some(32), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs index c9f3acffb77..722703d2384 100644 --- a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "ilp32d".into(), max_atomic_width: Some(32), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs index 75a65a26849..75a65a26849 100644 --- a/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs index f2242bbe087..f2242bbe087 100644 --- a/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/riscv32imac_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs index 25f5c3bc2a6..25f5c3bc2a6 100644 --- a/compiler/rustc_target/src/spec/riscv32imac_esp_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs diff --git a/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs index 55c6e4d16e5..55c6e4d16e5 100644 --- a/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs index a263e5d5cde..a263e5d5cde 100644 --- a/compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs diff --git a/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs index 3aa9923ee4d..3aa9923ee4d 100644 --- a/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs diff --git a/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs index 01e773fae97..01e773fae97 100644 --- a/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs index 121237f6ba4..40e447dbb83 100644 --- a/compiler/rustc_target/src/spec/riscv64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, CodeModel, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { llvm_abiname: "lp64d".into(), supported_sanitizers: SanitizerSet::ADDRESS, max_atomic_width: Some(64), - ..super::android_base::opts() + ..base::android::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs index 8281bac10f8..2c7878de812 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), - ..super::freebsd_base::opts() + ..base::freebsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs index 0585ed76fe8..a29470c24fb 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions}; +use crate::spec::{base, CodeModel, SanitizerSet, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), supported_sanitizers: SanitizerSet::SHADOWCALLSTACK, - ..super::fuchsia_base::opts() + ..base::fuchsia::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs index 1f6a34c0cac..b7e29d2da3d 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, RelocModel, Target, TargetOptions, TlsModel}; +use crate::spec::{base, CodeModel, RelocModel, Target, TargetOptions, TlsModel}; pub fn target() -> Target { Target { @@ -14,7 +14,7 @@ pub fn target() -> Target { tls_model: TlsModel::LocalExec, max_atomic_width: Some(64), llvm_abiname: "lp64d".into(), - ..super::hermit_base::opts() + ..base::hermit::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs index 90dccb28063..c0969d4e11e 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs index 1a56c78e685..656e260d094 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs index a89bd363a47..43a313a9408 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), mcount: "__mcount".into(), - ..super::netbsd_base::opts() + ..base::netbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs index ab3c14e3fe7..f29e224244e 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs @@ -1,8 +1,7 @@ +use crate::spec::SanitizerSet; use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy}; use crate::spec::{RelocModel, Target, TargetOptions}; -use super::SanitizerSet; - pub fn target() -> Target { Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs index ade9d77624b..1f1da7d5a29 100644 --- a/compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), - ..super::openbsd_base::opts() + ..base::openbsd::opts() }, } } diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs index 0f1821c9985..0f1821c9985 100644 --- a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs index f2c722b9a89..6fc410eb223 100644 --- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM base.cpu = "z10".into(); diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs index 8fe9d023c52..03772aab372 100644 --- a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM base.cpu = "z10".into(); diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs index 39efd8f305c..20ec9a84e8b 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.endian = Endian::Big; base.cpu = "v9".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs index 38ab066b087..c8c0fd2e134 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.cpu = "v9".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs index 06a5f782a6d..82ce610066a 100644 --- a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::openbsd_base::opts(); + let mut base = base::openbsd::opts(); base.endian = Endian::Big; base.cpu = "v9".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs index b10e6264b73..548fbb9ed52 100644 --- a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.endian = Endian::Big; base.cpu = "v9".into(); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs index 7e908a0f365..7e908a0f365 100644 --- a/compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs index 4d2bc98ab78..16cd991dd28 100644 --- a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs @@ -1,8 +1,8 @@ use crate::abi::Endian; -use crate::spec::{Cc, LinkerFlavor, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut base = super::solaris_base::opts(); + let mut base = base::solaris::opts(); base.endian = Endian::Big; base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); // llvm calls this "v9" diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs index 88a76f49acd..7b5c019b1bb 100644 --- a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs @@ -9,8 +9,8 @@ //! The default link script is very likely wrong, so you should use //! `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script. +use crate::spec::{base, PanicStrategy, RelocModel, Target, TargetOptions}; use crate::spec::{cvs, FramePointer}; -use crate::spec::{PanicStrategy, RelocModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -53,7 +53,7 @@ pub fn target() -> Target { atomic_cas: false, has_thumb_interworking: true, - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs index 021b0e0eb62..d9212afb084 100644 --- a/compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs @@ -1,6 +1,6 @@ //! Targets the ARMv5TE, with code as `t32` code by default. -use crate::spec::{cvs, FramePointer, Target, TargetOptions}; +use crate::spec::{base, cvs, FramePointer, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -35,7 +35,7 @@ pub fn target() -> Target { atomic_cas: false, has_thumb_interworking: true, - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs index c9bb0112f0e..ac076fb8864 100644 --- a/compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs @@ -1,6 +1,6 @@ // Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture) -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -19,7 +19,7 @@ pub fn target() -> Target { // There are no atomic CAS instructions available in the instruction set of the ARMv6-M // architecture atomic_cas: false, - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs index f1be274f067..128ac1dd179 100644 --- a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::{LinkerFlavor, Lld, PanicStrategy, Target, TargetOptions}; +use crate::spec::{base, LinkerFlavor, Lld, PanicStrategy, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::windows_msvc_base::opts(); + let mut base = base::windows_msvc::opts(); // Prevent error LNK2013: BRANCH24(T) fixup overflow // The LBR optimization tries to eliminate branch islands, // but if the displacement is larger than can fit diff --git a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs index 65c2f5a704b..810ed6a2404 100644 --- a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs @@ -1,4 +1,4 @@ -use crate::spec::{PanicStrategy, Target, TargetOptions}; +use crate::spec::{base, PanicStrategy, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is // implemented for windows/arm in LLVM panic_strategy: PanicStrategy::Abort, - ..super::windows_uwp_msvc_base::opts() + ..base::windows_uwp_msvc::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs index 000e5f2d3c6..1752f1d9aac 100644 --- a/compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs @@ -9,7 +9,7 @@ // To opt-in to hardware accelerated floating point operations, you can use, for example, // `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`. -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -21,7 +21,7 @@ pub fn target() -> Target { options: TargetOptions { abi: "eabi".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs index 39a72564e49..c113c62fc1d 100644 --- a/compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs @@ -8,7 +8,7 @@ // // To opt into double precision hardware support, use the `-C target-feature=+fp64` flag. -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -30,7 +30,7 @@ pub fn target() -> Target { // ARMv7-M Architecture Reference Manual - A2.5 The optional floating-point extension features: "+vfp4,-d32,-fp64".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs index ab25cde66c7..f9ab3ce1ad0 100644 --- a/compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs @@ -1,6 +1,6 @@ // Targets the Cortex-M3 processor (ARMv7-M) -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,7 +12,7 @@ pub fn target() -> Target { options: TargetOptions { abi: "eabi".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs index 624837a22d6..c07aa944d7e 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs @@ -1,4 +1,4 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; // This target if is for the Android v7a ABI in thumb mode with // NEON unconditionally enabled and, therefore, with 32 FPU registers @@ -9,7 +9,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; // for target ABI requirements. pub fn target() -> Target { - let mut base = super::android_base::opts(); + let mut base = base::android::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]); Target { llvm_target: "armv7-none-linux-android".into(), diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs index b500c50de98..b4045037c6a 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for glibc Linux on ARMv7 with thumb mode enabled // (for consistency with Android and Debian-based distributions) @@ -17,7 +17,7 @@ pub fn target() -> Target { // Info about features at https://wiki.debian.org/ArmHardFloatPort features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(), max_atomic_width: Some(64), - ..super::linux_gnu_base::opts() + ..base::linux_gnu::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs index dce0cbcef02..6ef30f10fe4 100644 --- a/compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; // This target is for musl Linux on ARMv7 with thumb mode enabled // (for consistency with Android and Debian-based distributions) @@ -23,7 +23,7 @@ pub fn target() -> Target { features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(), max_atomic_width: Some(64), mcount: "\u{1}mcount".into(), - ..super::linux_musl_base::opts() + ..base::linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs index 756b1834c82..bf62574867a 100644 --- a/compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs @@ -1,6 +1,6 @@ // Targets the Cortex-M23 processor (Baseline ARMv8-M) -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -15,7 +15,7 @@ pub fn target() -> Target { // with +strict-align. features: "+strict-align".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs index 4b626854654..07fc7feade5 100644 --- a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs @@ -1,7 +1,7 @@ // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile), // without the Floating Point extension. -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { options: TargetOptions { abi: "eabi".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs index 86c25f9e4b9..61d4e8fc802 100644 --- a/compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs @@ -1,7 +1,7 @@ // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile), // with the Floating Point extension. -use crate::spec::{Target, TargetOptions}; +use crate::spec::{base, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -19,7 +19,7 @@ pub fn target() -> Target { // These parameters map to the following LLVM features. features: "+fp-armv8,-fp64,-d32".into(), max_atomic_width: Some(32), - ..super::thumb_base::opts() + ..base::thumb::opts() }, } } diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs index 6f77ef98c01..394f02ecac4 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs @@ -1,5 +1,6 @@ -use super::{cvs, wasm_base}; -use super::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; +use crate::spec::{ + base, cvs, LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions, +}; pub fn target() -> Target { // Reset flags for non-Em flavors back to empty to satisfy sanity checking tests. @@ -22,7 +23,7 @@ pub fn target() -> Target { panic_strategy: PanicStrategy::Unwind, no_default_libraries: false, families: cvs!["unix", "wasm"], - ..wasm_base::options() + ..base::wasm::options() }; Target { llvm_target: "wasm32-unknown-emscripten".into(), diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs index 06529c2e403..2a40d9c6637 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs @@ -10,11 +10,11 @@ //! This target is more or less managed by the Rust and WebAssembly Working //! Group nowadays at <https://github.com/rustwasm>. -use super::{wasm_base, Cc, LinkerFlavor, Target}; use crate::spec::abi::Abi; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut options = wasm_base::options(); + let mut options = base::wasm::options(); options.os = "unknown".into(); // This is a default for backwards-compatibility with the original diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs index 23fabcdc90d..6dbcb01ea43 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs @@ -72,12 +72,12 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use super::crt_objects; -use super::LinkSelfContainedDefault; -use super::{wasm_base, Cc, LinkerFlavor, Target}; +use crate::spec::crt_objects; +use crate::spec::LinkSelfContainedDefault; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut options = wasm_base::options(); + let mut options = base::wasm::options(); options.os = "wasi".into(); options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasi"]); diff --git a/compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs index ba9a99ae380..28ea4cc9ece 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs @@ -72,11 +72,10 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use super::{crt_objects, wasm_base}; -use super::{Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; +use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; pub fn target() -> Target { - let mut options = wasm_base::options(); + let mut options = base::wasm::options(); options.os = "wasi".into(); diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs index 3fda398d24c..54c5ae8e203 100644 --- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs @@ -7,10 +7,10 @@ //! the standard library is available, most of it returns an error immediately //! (e.g. trying to create a TCP stream or something like that). -use super::{wasm_base, Cc, LinkerFlavor, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { - let mut options = wasm_base::options(); + let mut options = base::wasm::options(); options.os = "unknown".into(); options.add_pre_link_args( diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index e3f5d7321d1..9170a10d254 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -1,4 +1,4 @@ -use super::apple_base::{macos_llvm_target, opts, Arch}; +use crate::spec::base::apple::{macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet}; use crate::spec::{StackProbeType, Target, TargetOptions}; diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs index 061b6a96fc8..d9f3f7de655 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_base::{ios_sim_llvm_target, opts, Arch}; +use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs index fd1926f2945..5e6fbac34d7 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, Arch}; +use crate::spec::base::apple::{opts, Arch}; use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs index 2ec4d9569e3..1c4d9196c18 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, tvos_sim_llvm_target, Arch}; +use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs index 5fcc00a86ff..258148677fb 100644 --- a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs @@ -1,4 +1,4 @@ -use super::apple_base::{opts, watchos_sim_llvm_target, Arch}; +use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch}; use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { diff --git a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs index a7ed74f4721..f4117edc3ff 100644 --- a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use super::{cvs, Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{cvs, Cc, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { let pre_link_args = TargetOptions::link_args( diff --git a/compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs new file mode 100644 index 00000000000..46df00e9c02 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs @@ -0,0 +1 @@ +pub use crate::spec::targets::x86_64_unknown_fuchsia::target; diff --git a/compiler/rustc_target/src/spec/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs index c110674fd87..6cffda44fa9 100644 --- a/compiler/rustc_target/src/spec/x86_64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs @@ -1,7 +1,9 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions}; +use crate::spec::{ + base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions, +}; pub fn target() -> Target { - let mut base = super::android_base::opts(); + let mut base = base::android::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; // https://developer.android.com/ndk/guides/abis.html#86-64 diff --git a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs index 8424757df07..93aec4c425a 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs @@ -1,5 +1,4 @@ -use super::nto_qnx_base; -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -17,7 +16,7 @@ pub fn target() -> Target { &["-Vgcc_ntox86_64_cxx"], ), env: "nto71".into(), - ..nto_qnx_base::opts() + ..base::nto_qnx::opts() }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs index e2c59d2938e..ca6a6dc500b 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::solaris_base::opts(); + let mut base = base::solaris::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs index 1b8885c34da..6d3e0727051 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_gnu_base::opts(); + let mut base = base::windows_gnu::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; // Use high-entropy 64 bit address space for ASLR diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs index 8f5e398a0be..a56ebfa585e 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_gnullvm_base::opts(); + let mut base = base::windows_gnullvm::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs index 6b897ca7070..7d6276a0c2d 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_msvc_base::opts(); + let mut base = base::windows_msvc::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_sun_solaris.rs index 650065f6330..cca099d3bbf 100644 --- a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_sun_solaris.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::solaris_base::opts(); + let mut base = base::solaris::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs index 2aa093b131f..c12cb1ab00e 100644 --- a/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]), max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..super::unikraft_linux_musl_base::opts() + ..base::unikraft_linux_musl::opts() }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs index 3b8e75977b5..68d1a755b79 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::dragonfly_base::opts(); + let mut base = base::dragonfly::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs index b2d91d09996..e3f29fa5afa 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::freebsd_base::opts(); + let mut base = base::freebsd::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs index bee93541960..c8850d703e3 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs @@ -1,7 +1,7 @@ -use crate::spec::{SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::fuchsia_base::opts(); + let mut base = base::fuchsia::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs index 16ed3150e6e..ca55e6514dd 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::haiku_base::opts(); + let mut base = base::haiku::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs index 1eb06930111..3cc50d40dda 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs @@ -1,4 +1,4 @@ -use crate::spec::{StackProbeType, Target, TargetOptions}; +use crate::spec::{base, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,7 +13,7 @@ pub fn target() -> Target { plt_by_default: false, max_atomic_width: Some(64), stack_probes: StackProbeType::X86, - ..super::hermit_base::opts() + ..base::hermit::opts() }, } } diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs index 9259cfe5f0e..eb2b13cb5c2 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, SanitizerSet, Target}; +use crate::spec::{base, Cc, LinkerFlavor, SanitizerSet, Target}; pub fn target() -> Target { - let mut base = super::illumos_base::opts(); + let mut base = base::illumos::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64", "-std=c99"]); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs index 912d289c47f..7b86fe738b1 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs @@ -1,7 +1,7 @@ -use crate::spec::{PanicStrategy, Target}; +use crate::spec::{base, PanicStrategy, Target}; pub fn target() -> Target { - let mut base = super::l4re_base::opts(); + let mut base = base::l4re::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs index 2f970f87cc6..80e267c163f 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs index 5469d02c592..622bfe8bbe8 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_gnu_base::opts(); + let mut base = base::linux_gnu::opts(); base.cpu = "x86-64".into(); base.abi = "x32".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs index 7154f5fa306..d74ff466a01 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_musl_base::opts(); + let mut base = base::linux_musl::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs index a96be8cd554..87b004df001 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::linux_ohos_base::opts(); + let mut base = base::linux_ohos::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs index 2e7bf34f7d2..04060513abc 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs @@ -1,7 +1,9 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions}; +use crate::spec::{ + base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions, +}; pub fn target() -> Target { - let mut base = super::netbsd_base::opts(); + let mut base = base::netbsd::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs index fe3b24f2d4a..9aa95a35f8e 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs @@ -4,8 +4,8 @@ // `target-cpu` compiler flags to opt-in more hardware-specific // features. -use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy}; -use super::{RelroLevel, SanitizerSet, StackProbeType, Target, TargetOptions}; +use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy}; +use crate::spec::{RelroLevel, SanitizerSet, StackProbeType, Target, TargetOptions}; pub fn target() -> Target { let opts = TargetOptions { diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs index 86fa9bf7ed2..5e6e7efb2de 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::openbsd_base::opts(); + let mut base = base::openbsd::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs index decc9736782..382ff71f019 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::redox_base::opts(); + let mut base = base::redox::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs index 41ba768068a..5abfb8162f7 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs @@ -5,10 +5,13 @@ // The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with // LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features. -use crate::{abi::call::Conv, spec::Target}; +use crate::{ + abi::call::Conv, + spec::{base, Target}, +}; pub fn target() -> Target { - let mut base = super::uefi_msvc_base::opts(); + let mut base = base::uefi_msvc::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs index 1a9d2a57182..a46d3a0e27b 100644 --- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; pub fn target() -> Target { - let mut base = super::windows_uwp_gnu_base::opts(); + let mut base = base::windows_uwp_gnu::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; // Use high-entropy 64 bit address space for ASLR diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs index 1ae403fa83f..a3bc27aa065 100644 --- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs @@ -1,7 +1,7 @@ -use crate::spec::Target; +use crate::spec::{base, Target}; pub fn target() -> Target { - let mut base = super::windows_uwp_msvc_base::opts(); + let mut base = base::windows_uwp_msvc::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs index a7c4aaecf91..4b221fe6959 100644 --- a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs @@ -1,7 +1,7 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; pub fn target() -> Target { - let mut base = super::vxworks_base::opts(); + let mut base = base::vxworks::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index 54f7490b2c0..a30e9d17cef 100644 --- a/compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs @@ -1,4 +1,4 @@ -use super::apple_base::{macos_llvm_target, opts, Arch}; +use crate::spec::base::apple::{macos_llvm_target, opts, Arch}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet}; use crate::spec::{StackProbeType, Target, TargetOptions}; diff --git a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs deleted file mode 100644 index 96fed097566..00000000000 --- a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs +++ /dev/null @@ -1 +0,0 @@ -pub use crate::spec::x86_64_unknown_fuchsia::target; diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 5ba29f87855..6fab9441bdc 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -21,7 +21,6 @@ #![feature(let_chains)] #![feature(if_let_guard)] #![feature(never_type)] -#![feature(result_option_inspect)] #![feature(type_alias_impl_trait)] #![feature(min_specialization)] #![recursion_limit = "512"] // For rustdoc diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index d655a4106b8..6eefccbde04 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -14,6 +14,7 @@ use crate::solve::EvalCtxt; // // For types with an "existential" binder, i.e. coroutine witnesses, we also // instantiate the binder with placeholders eagerly. +#[instrument(level = "debug", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, @@ -90,13 +91,13 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, ) -> ty::Binder<'tcx, Ty<'tcx>> { - debug_assert!(!ty.has_late_bound_regions()); + debug_assert!(!ty.has_bound_regions()); let mut counter = 0; let ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() { ty::ReErased => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon }; counter += 1; - ty::Region::new_late_bound(tcx, current_depth, br) + ty::Region::new_bound(tcx, current_depth, br) } // All free regions should be erased here. r => bug!("unexpected region: {r:?}"), @@ -107,6 +108,7 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( ty::Binder::bind_with_vars(ty, bound_vars) } +#[instrument(level = "debug", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, @@ -152,6 +154,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( } } +#[instrument(level = "debug", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index 377ae1b4e85..5f08bc0039a 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -222,7 +222,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> { } let kind = match *r { - ty::ReLateBound(..) => return r, + ty::ReBound(..) => return r, // We may encounter `ReStatic` in item signatures or the hidden type // of an opaque. `ReErased` should only be encountered in the hidden @@ -278,7 +278,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> { var }); let br = ty::BoundRegion { var, kind: BrAnon }; - ty::Region::new_late_bound(self.interner(), self.binder_index, br) + ty::Region::new_bound(self.interner(), self.binder_index, br) } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index b3f9218d761..ae7f6ca2f7a 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -262,7 +262,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } GenericArgKind::Lifetime(r) => { - if let ty::ReLateBound(debruijn, br) = *r { + if let ty::ReBound(debruijn, br) = *r { assert_eq!(debruijn, ty::INNERMOST); opt_values[br.var] = Some(*original_value); } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 70235b710e2..583eb9f96a9 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -4,7 +4,7 @@ use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ - DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, TyCtxtInferExt, + BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt, }; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::ObligationCause; @@ -780,7 +780,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ) -> T { self.infcx.instantiate_binder_with_fresh_vars( DUMMY_SP, - LateBoundRegionConversionTime::HigherRankedType, + BoundRegionConversionTime::HigherRankedType, value, ) } diff --git a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs index 240141065dc..7fb550aa3e0 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs @@ -160,7 +160,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; - if !drcx.args_refs_may_unify(goal_trait_ref.args, impl_trait_ref.skip_binder().args) { + if !drcx.args_may_unify(goal_trait_ref.args, impl_trait_ref.skip_binder().args) { return Err(NoSolution); } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index a0e2ad6e202..84baec4ff4c 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -43,9 +43,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; - if !drcx - .args_refs_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args) - { + if !drcx.args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args) { return Err(NoSolution); } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 8096d7969f3..dbf6749b523 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -410,11 +410,11 @@ impl<'tcx> AutoTraitFinder<'tcx> { iter::zip(new_args.regions(), old_args.regions()) { match (*new_region, *old_region) { - // If both predicates have an `ReLateBound` (a HRTB) in the + // If both predicates have an `ReBound` (a HRTB) in the // same spot, we do nothing. - (ty::ReLateBound(_, _), ty::ReLateBound(_, _)) => {} + (ty::ReBound(_, _), ty::ReBound(_, _)) => {} - (ty::ReLateBound(_, _), _) | (_, ty::ReVar(_)) => { + (ty::ReBound(_, _), _) | (_, ty::ReVar(_)) => { // One of these is true: // The new predicate has a HRTB in a spot where the old // predicate does not (if they both had a HRTB, the previous @@ -440,7 +440,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // `user_computed_preds`. return false; } - (_, ty::ReLateBound(_, _)) | (ty::ReVar(_), _) => { + (_, ty::ReBound(_, _)) | (ty::ReVar(_), _) => { // This is the opposite situation as the previous arm. // One of these is true: // diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index dcf5fd86929..787d8063005 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -100,7 +100,7 @@ pub fn overlapping_impls( let impl1_ref = tcx.impl_trait_ref(impl1_def_id); let impl2_ref = tcx.impl_trait_ref(impl2_def_id); let may_overlap = match (impl1_ref, impl2_ref) { - (Some(a), Some(b)) => drcx.args_refs_may_unify(a.skip_binder().args, b.skip_binder().args), + (Some(a), Some(b)) => drcx.args_may_unify(a.skip_binder().args, b.skip_binder().args), (None, None) => { let self_ty1 = tcx.type_of(impl1_def_id).skip_binder(); let self_ty2 = tcx.type_of(impl2_def_id).skip_binder(); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index 5bc5a12a8fe..b246e476bed 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -1,5 +1,5 @@ use rustc_hir::def_id::DefId; -use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime}; +use rustc_infer::infer::{BoundRegionConversionTime, InferCtxt}; use rustc_infer::traits::util::elaborate; use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation}; use rustc_middle::ty; @@ -53,7 +53,7 @@ pub fn recompute_applicable_impls<'tcx>( let param_env_predicate = infcx.instantiate_binder_with_fresh_vars( DUMMY_SP, - LateBoundRegionConversionTime::HigherRankedType, + BoundRegionConversionTime::HigherRankedType, poly_trait_predicate, ); let param_env_trait_ref = diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 31da437f2e9..262bed8610c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -26,8 +26,9 @@ use rustc_hir::{CoroutineKind, CoroutineSource, Node}; use rustc_hir::{Expr, HirId}; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{DefineOpaqueTypes, InferOk, LateBoundRegionConversionTime}; +use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk}; use rustc_middle::hir::map; +use rustc_middle::traits::IsConstable; use rustc_middle::ty::error::TypeError::{self, Sorts}; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs, @@ -739,7 +740,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } // We `erase_late_bound_regions` here because `make_subregion` does not handle - // `ReLateBound`, and we don't particularly care about the regions. + // `ReBound`, and we don't particularly care about the regions. let real_ty = self.tcx.erase_late_bound_regions(real_trait_pred.self_ty()); if !self.can_eq(obligation.param_env, real_ty, arg_ty) { continue; @@ -907,7 +908,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let self_ty = self.instantiate_binder_with_fresh_vars( DUMMY_SP, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, trait_pred.self_ty(), ); @@ -1236,7 +1237,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let output = self.instantiate_binder_with_fresh_vars( DUMMY_SP, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, output, ); let inputs = inputs @@ -1245,7 +1246,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .map(|ty| { self.instantiate_binder_with_fresh_vars( DUMMY_SP, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, inputs.rebind(*ty), ) }) @@ -2768,20 +2769,30 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { )); } } - ObligationCauseCode::RepeatElementCopy { is_const_fn } => { + ObligationCauseCode::RepeatElementCopy { is_constable, elt_type, elt_span, elt_stmt_span } => { err.note( "the `Copy` trait is required because this value will be copied for each element of the array", ); - - if is_const_fn { - err.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];`", - ); + let value_kind = match is_constable { + IsConstable::Fn => Some("the result of the function call"), + IsConstable::Ctor => Some("the result of the constructor"), + _ => None + }; + let sm = tcx.sess.source_map(); + if let Some(value_kind) = value_kind && + let Ok(snip) = sm.span_to_snippet(elt_span) + { + let help_msg = format!( + "consider creating a new `const` item and initializing it with {value_kind} \ + to be used in the repeat position"); + let indentation = sm.indentation_before(elt_stmt_span).unwrap_or_default(); + err.multipart_suggestion(help_msg, vec![ + (elt_stmt_span.shrink_to_lo(), format!("const ARRAY_REPEAT_VALUE: {elt_type} = {snip};\n{indentation}")), + (elt_span, "ARRAY_REPEAT_VALUE".to_string()) + ], Applicability::MachineApplicable); } - if self.tcx.sess.is_nightly_build() && is_const_fn { + if self.tcx.sess.is_nightly_build() && matches!(is_constable, IsConstable::Fn|IsConstable::Ctor) { err.help( "create an inline `const` block, see RFC #2920 \ <https://github.com/rust-lang/rfcs/pull/2920> for more information", @@ -2938,7 +2949,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { else { bug!("expected closure in SizedClosureCapture obligation"); }; - if let hir::CaptureBy::Value = closure.capture_clause + if let hir::CaptureBy::Value { .. } = closure.capture_clause && let Some(span) = closure.fn_arg_span { err.span_label(span, "this closure captures all values by move"); @@ -3584,7 +3595,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let where_pred = self.instantiate_binder_with_placeholders(where_pred); let failed_pred = self.instantiate_binder_with_fresh_vars( expr.span, - LateBoundRegionConversionTime::FnCall, + BoundRegionConversionTime::FnCall, failed_pred, ); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index ba2e3d1ae28..aa284cfc9c5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1377,7 +1377,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { { let data = self.instantiate_binder_with_fresh_vars( obligation.cause.span, - infer::LateBoundRegionConversionTime::HigherRankedType, + infer::BoundRegionConversionTime::HigherRankedType, bound_predicate.rebind(data), ); let unnormalized_term = match data.term.unpack() { diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 17c7f94ee88..3e5dd8c50d4 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -329,7 +329,7 @@ fn super_predicates_have_non_lifetime_binders( tcx.super_predicates_of(trait_def_id) .predicates .iter() - .filter_map(|(pred, span)| pred.has_non_region_late_bound().then_some(*span)) + .filter_map(|(pred, span)| pred.has_non_region_bound_vars().then_some(*span)) .collect() } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e4f7592c409..3bc401128b3 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -18,7 +18,7 @@ use rustc_middle::traits::ImplSourceUserDefinedData; use crate::errors::InherentProjectionNormalizationOverflow; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; +use crate::infer::{BoundRegionConversionTime, InferCtxt, InferOk}; use crate::traits::error_reporting::TypeErrCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::select::ProjectionMatchesProjection; @@ -783,7 +783,7 @@ pub struct BoundVarReplacer<'me, 'tcx> { // the `var` (but we *could* bring that into scope if we were to track them as we pass them). mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>, mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>, - mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>, + mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>, // The current depth relative to *this* folding, *not* the entire normalization. In other words, // the depth of binders we've passed here. current_index: ty::DebruijnIndex, @@ -843,11 +843,11 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> { T, BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>, BTreeMap<ty::PlaceholderType, ty::BoundTy>, - BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>, + BTreeMap<ty::PlaceholderConst, ty::BoundVar>, ) { let mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion> = BTreeMap::new(); let mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy> = BTreeMap::new(); - let mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar> = BTreeMap::new(); + let mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar> = BTreeMap::new(); let mut replacer = BoundVarReplacer { infcx, @@ -894,16 +894,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, _) - if debruijn.as_usize() + 1 - > self.current_index.as_usize() + self.universe_indices.len() => + ty::ReBound(debruijn, _) + if debruijn.as_usize() + >= self.current_index.as_usize() + self.universe_indices.len() => { bug!( "Bound vars {r:#?} outside of `self.universe_indices`: {:#?}", self.universe_indices ); } - ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { + ty::ReBound(debruijn, br) if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); let p = ty::PlaceholderRegion { universe, bound: br }; self.mapped_regions.insert(p, br); @@ -966,7 +966,7 @@ pub struct PlaceholderReplacer<'me, 'tcx> { infcx: &'me InferCtxt<'tcx>, mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>, mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>, - mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>, + mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>, universe_indices: &'me [Option<ty::UniverseIndex>], current_index: ty::DebruijnIndex, } @@ -976,7 +976,7 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> { infcx: &'me InferCtxt<'tcx>, mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>, mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>, - mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>, + mapped_consts: BTreeMap<ty::PlaceholderConst, ty::BoundVar>, universe_indices: &'me [Option<ty::UniverseIndex>], value: T, ) -> T { @@ -1034,7 +1034,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> { let db = ty::DebruijnIndex::from_usize( self.universe_indices.len() - index + self.current_index.as_usize() - 1, ); - ty::Region::new_late_bound(self.interner(), db, *replace_var) + ty::Region::new_bound(self.interner(), db, *replace_var) } None => r1, } @@ -2319,7 +2319,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( let cache_entry = infcx.instantiate_binder_with_fresh_vars( cause.span, - LateBoundRegionConversionTime::HigherRankedType, + BoundRegionConversionTime::HigherRankedType, poly_cache_entry, ); diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 2e31b560b38..dba00ce0154 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -150,7 +150,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor { #[inline] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { match *r { - ty::ReLateBound(debruijn, _) if debruijn > self.outer_index => { + ty::ReBound(debruijn, _) if debruijn > self.outer_index => { self.escaping = self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize()); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 5c67188dd24..c1d44601891 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -375,7 +375,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // consider a "quick reject". This avoids creating more types // and so forth that we need to. let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); - if !drcx.args_refs_may_unify(obligation_args, impl_trait_ref.skip_binder().args) { + if !drcx.args_may_unify(obligation_args, impl_trait_ref.skip_binder().args) { return; } if self.reject_fn_ptr_impls( @@ -628,15 +628,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } self.infcx.probe(|_snapshot| { - if obligation.has_non_region_late_bound() { - return; - } + let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); + let placeholder_trait_predicate = + self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); - // The code below doesn't care about regions, and the - // self-ty here doesn't escape this probe, so just erase - // any LBR. - let self_ty = self.tcx().erase_late_bound_regions(obligation.self_ty()); - let poly_trait_ref = match self_ty.kind() { + let self_ty = placeholder_trait_predicate.self_ty(); + let principal_trait_ref = match self_ty.kind() { ty::Dynamic(ref data, ..) => { if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { debug!( @@ -668,18 +665,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => return, }; - debug!(?poly_trait_ref, "assemble_candidates_from_object_ty"); - - let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); - let placeholder_trait_predicate = - self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); + debug!(?principal_trait_ref, "assemble_candidates_from_object_ty"); // Count only those upcast versions that match the trait-ref // we are looking for. Specifically, do not only check for the // correct trait, but also the correct type parameters. // For example, we may be trying to upcast `Foo` to `Bar<i32>`, // but `Foo` is declared as `trait Foo: Bar<u32>`. - let candidate_supertraits = util::supertraits(self.tcx(), poly_trait_ref) + let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref) .enumerate() .filter(|&(_, upcast_trait_ref)| { self.infcx.probe(|_| { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 4bfa341e333..abb4e71a9af 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -9,7 +9,7 @@ use rustc_ast::Mutability; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; -use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; +use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch}; use rustc_middle::ty::{ @@ -592,7 +592,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, '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 { @@ -1277,7 +1277,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); stack.extend(tcx.coroutine_hidden_types(def_id).map(|bty| { let ty = bty.instantiate(tcx, args); - debug_assert!(!ty.has_late_bound_regions()); + debug_assert!(!ty.has_bound_regions()); ty })) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index cf52e6726a1..1ed0da59b64 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -32,8 +32,8 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::infer::DefineOpaqueTypes; -use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::traits::TraitObligation; use rustc_middle::dep_graph::dep_kinds; use rustc_middle::dep_graph::DepNodeIndex; @@ -799,7 +799,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // A global type with no free lifetimes or generic parameters // outlives anything. if pred.0.has_free_regions() - || pred.0.has_late_bound_regions() + || pred.0.has_bound_regions() || pred.0.has_non_region_infer() || pred.0.has_non_region_infer() { @@ -1751,7 +1751,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut nested_obligations = Vec::new(); let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars( obligation.cause.span, - LateBoundRegionConversionTime::HigherRankedType, + BoundRegionConversionTime::HigherRankedType, env_predicate, ); let infer_projection = if potentially_unnormalized_candidates { @@ -1841,7 +1841,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. let is_global = - |cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_late_bound_vars(); + |cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars(); // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, // `DiscriminantKindCandidate`, `ConstDestructCandidate` @@ -2389,12 +2389,21 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ) }); - let obligation = Obligation::new( - self.tcx(), - cause.clone(), - param_env, - ty::TraitRef::new(self.tcx(), trait_def_id, [normalized_ty]), - ); + let tcx = self.tcx(); + let trait_ref = if tcx.generics_of(trait_def_id).params.len() == 1 { + ty::TraitRef::new(tcx, trait_def_id, [normalized_ty]) + } else { + // If this is an ill-formed auto/built-in trait, then synthesize + // new error args for the missing generics. + let err_args = ty::GenericArgs::extend_with_error( + tcx, + trait_def_id, + &[normalized_ty.into()], + ); + ty::TraitRef::new(tcx, trait_def_id, err_args) + }; + + let obligation = Obligation::new(self.tcx(), cause.clone(), param_env, trait_ref); obligations.push(obligation); obligations }) @@ -3094,7 +3103,7 @@ fn bind_coroutine_hidden_types_above<'tcx>( kind: ty::BrAnon, }; counter += 1; - ty::Region::new_late_bound(tcx, current_depth, br) + ty::Region::new_bound(tcx, current_depth, br) } r => bug!("unexpected region: {r:?}"), }) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fe5b625e483..9751cb60ed8 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -913,20 +913,15 @@ pub fn object_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, existential_predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, ) -> Vec<ty::Region<'tcx>> { - // Since we don't actually *know* the self type for an object, - // this "open(err)" serves as a kind of dummy standin -- basically - // a placeholder type. - let open_ty = Ty::new_fresh(tcx, 0); - let predicates = existential_predicates.iter().filter_map(|predicate| { if let ty::ExistentialPredicate::Projection(_) = predicate.skip_binder() { None } else { - Some(predicate.with_self_ty(tcx, open_ty)) + Some(predicate.with_self_ty(tcx, tcx.types.trait_object_dummy_self)) } }); - required_region_bounds(tcx, open_ty, predicates) + required_region_bounds(tcx, tcx.types.trait_object_dummy_self, predicates) } /// Given a set of predicates that apply to an object type, returns diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 2563e3ed1a3..cb2a36cb998 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -4,18 +4,12 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::{Normalized, ObligationCause}; -use std::sync::atomic::Ordering; pub(crate) fn provide(p: &mut Providers) { *p = Providers { try_normalize_generic_arg_after_erasing_regions: |tcx, goal| { debug!("try_normalize_generic_arg_after_erasing_regions(goal={:#?}", goal); - tcx.sess - .perf_stats - .normalize_generic_arg_after_erasing_regions - .fetch_add(1, Ordering::Relaxed); - try_normalize_after_erasing_regions(tcx, goal) }, ..*p diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 01bb1ca70eb..b8c71bc96f8 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -10,7 +10,6 @@ use rustc_trait_selection::traits::query::{ use rustc_trait_selection::traits::{ self, FulfillmentErrorCode, ObligationCause, SelectionContext, }; -use std::sync::atomic::Ordering; pub(crate) fn provide(p: &mut Providers) { *p = Providers { @@ -27,7 +26,6 @@ fn normalize_projection_ty<'tcx>( ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> { debug!("normalize_provider(goal={:#?})", goal); - tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed); tcx.infer_ctxt().enter_canonical_trait_query( &goal, |ocx, ParamEnvAnd { param_env, value: goal }| { @@ -78,7 +76,6 @@ fn normalize_weak_ty<'tcx>( ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> { debug!("normalize_provider(goal={:#?})", goal); - tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed); tcx.infer_ctxt().enter_canonical_trait_query( &goal, |ocx, ParamEnvAnd { param_env, value: goal }| { diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index fcf6626bbf0..38f2d616f9a 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -82,7 +82,7 @@ fn fn_sig_for_fn_abi<'tcx>( var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BoundRegionKind::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 env_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap(); let sig = sig.skip_binder(); @@ -107,8 +107,7 @@ fn fn_sig_for_fn_abi<'tcx>( var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BoundRegionKind::BrEnv, }; - let env_ty = - Ty::new_mut_ref(tcx, ty::Region::new_late_bound(tcx, ty::INNERMOST, br), ty); + let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty); let pin_did = tcx.require_lang_item(LangItem::Pin, None); let pin_adt_ref = tcx.adt_def(pin_did); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 283862b5e1c..52f723eba80 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -740,11 +740,11 @@ fn coroutine_layout<'tcx>( }; let tag_layout = cx.tcx.mk_layout(LayoutS::scalar(cx, tag)); - let promoted_layouts = ineligible_locals - .iter() - .map(|local| subst_field(info.field_tys[local].ty)) - .map(|ty| Ty::new_maybe_uninit(tcx, ty)) - .map(|ty| Ok(cx.layout_of(ty)?.layout)); + let promoted_layouts = ineligible_locals.iter().map(|local| { + let field_ty = subst_field(info.field_tys[local].ty); + let uninit_ty = Ty::new_maybe_uninit(tcx, field_ty); + Ok(cx.spanned_layout_of(uninit_ty, info.field_tys[local].source_info.span)?.layout) + }); let prefix_layouts = args .as_coroutine() .prefix_tys() diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index abf3e108ed4..2b262cfdebd 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -195,7 +195,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { // bounds of the RPITIT. Shift these binders back out when // constructing the top-level projection predicate. let shifted_alias_ty = self.tcx.fold_regions(unshifted_alias_ty, |re, depth| { - if let ty::ReLateBound(index, bv) = re.kind() { + if let ty::ReBound(index, bv) = re.kind() { if depth != ty::INNERMOST { return ty::Region::new_error_with_message( self.tcx, @@ -203,7 +203,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { "we shouldn't walk non-predicate binders with `impl Trait`...", ); } - ty::Region::new_late_bound( + ty::Region::new_bound( self.tcx, index.shifted_out_to_binder(self.depth), bv, diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index c8e730b585a..ace9eade7f6 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -3,18 +3,17 @@ use std::hash::Hash; use std::ops::ControlFlow; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_serialize::{Decodable, Encodable}; use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; -use crate::TyDecoder; -use crate::{HashStableContext, Interner, TyEncoder, UniverseIndex}; +use crate::{HashStableContext, Interner, UniverseIndex}; /// A "canonicalized" type `V` is one where all free inference /// variables have been rewritten to "canonical vars". These are /// numbered starting from 0 in order of first appearance. #[derive(derivative::Derivative)] #[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))] +#[derive(TyEncodable, TyDecodable)] pub struct Canonical<I: Interner, V> { pub value: V, pub max_universe: UniverseIndex, @@ -127,27 +126,3 @@ where self.variables.visit_with(folder) } } - -impl<I: Interner, E: TyEncoder<I = I>, V: Encodable<E>> Encodable<E> for Canonical<I, V> -where - I::CanonicalVars: Encodable<E>, -{ - fn encode(&self, s: &mut E) { - self.value.encode(s); - self.max_universe.encode(s); - self.variables.encode(s); - } -} - -impl<I: Interner, D: TyDecoder<I = I>, V: Decodable<D>> Decodable<D> for Canonical<I, V> -where - I::CanonicalVars: Decodable<D>, -{ - fn decode(d: &mut D) -> Self { - Canonical { - value: Decodable::decode(d), - max_universe: Decodable::decode(d), - variables: Decodable::decode(d), - } - } -} diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index cf67ba0b21a..33782b13ca8 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_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}; use std::fmt; -use crate::{ - DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, TyDecoder, - TyEncoder, WithInfcx, -}; +use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx}; use self::ConstKind::*; @@ -20,6 +16,7 @@ use self::ConstKind::*; Ord = "feature_allow_slow_enum", Hash(bound = "") )] +#[derive(TyEncodable, TyDecodable)] pub enum ConstKind<I: Interner> { /// A const generic parameter. Param(I::ParamConst), @@ -92,67 +89,6 @@ where } } -impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ConstKind<I> -where - I::ParamConst: Decodable<D>, - I::InferConst: Decodable<D>, - I::BoundConst: Decodable<D>, - I::PlaceholderConst: Decodable<D>, - I::AliasConst: Decodable<D>, - I::ValueConst: Decodable<D>, - I::ErrorGuaranteed: Decodable<D>, - I::ExprConst: Decodable<D>, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => Param(Decodable::decode(d)), - 1 => Infer(Decodable::decode(d)), - 2 => Bound(Decodable::decode(d), Decodable::decode(d)), - 3 => Placeholder(Decodable::decode(d)), - 4 => Unevaluated(Decodable::decode(d)), - 5 => Value(Decodable::decode(d)), - 6 => Error(Decodable::decode(d)), - 7 => Expr(Decodable::decode(d)), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "ConstKind", 8, - ) - ), - } - } -} - -impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for ConstKind<I> -where - I::ParamConst: Encodable<E>, - I::InferConst: Encodable<E>, - I::BoundConst: Encodable<E>, - I::PlaceholderConst: Encodable<E>, - I::AliasConst: Encodable<E>, - I::ValueConst: Encodable<E>, - I::ErrorGuaranteed: Encodable<E>, - I::ExprConst: Encodable<E>, -{ - fn encode(&self, e: &mut E) { - let disc = const_kind_discriminant(self); - match self { - Param(p) => e.emit_enum_variant(disc, |e| p.encode(e)), - Infer(i) => e.emit_enum_variant(disc, |e| i.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)), - Unevaluated(u) => e.emit_enum_variant(disc, |e| u.encode(e)), - Value(v) => e.emit_enum_variant(disc, |e| v.encode(e)), - Error(er) => e.emit_enum_variant(disc, |e| er.encode(e)), - Expr(ex) => e.emit_enum_variant(disc, |e| ex.encode(e)), - } - } -} - impl<I: Interner> PartialEq for ConstKind<I> { fn eq(&self, other: &Self) -> bool { match (self, other) { diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index d5cadd4e83a..d10927b0d93 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -85,20 +85,20 @@ bitflags! { const HAS_ERROR = 1 << 14; /// Does this have any region that "appears free" in the type? - /// Basically anything but `ReLateBound` and `ReErased`. + /// Basically anything but `ReBound` and `ReErased`. const HAS_FREE_REGIONS = 1 << 15; - /// Does this have any `ReLateBound` regions? - const HAS_RE_LATE_BOUND = 1 << 16; + /// Does this have any `ReBound` regions? + const HAS_RE_BOUND = 1 << 16; /// Does this have any `Bound` types? - const HAS_TY_LATE_BOUND = 1 << 17; + const HAS_TY_BOUND = 1 << 17; /// Does this have any `ConstKind::Bound` consts? - const HAS_CT_LATE_BOUND = 1 << 18; + const HAS_CT_BOUND = 1 << 18; /// Does this have any bound variables? /// Used to check if a global bound is safe to evaluate. - const HAS_LATE_BOUND = TypeFlags::HAS_RE_LATE_BOUND.bits - | TypeFlags::HAS_TY_LATE_BOUND.bits - | TypeFlags::HAS_CT_LATE_BOUND.bits; + const HAS_BOUND_VARS = TypeFlags::HAS_RE_BOUND.bits + | TypeFlags::HAS_TY_BOUND.bits + | TypeFlags::HAS_CT_BOUND.bits; /// Does this have any `ReErased` regions? const HAS_RE_ERASED = 1 << 19; @@ -115,5 +115,8 @@ bitflags! { /// Does this have `Coroutine` or `CoroutineWitness`? const HAS_TY_COROUTINE = 1 << 23; + + /// Does this have any binders with bound vars (e.g. that need to be anonymized)? + const HAS_BINDER_VARS = 1 << 24; } } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index a056fbeda98..e8785fff2ef 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -10,6 +10,8 @@ #![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] +extern crate self as rustc_type_ir; + #[macro_use] extern crate bitflags; #[macro_use] diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 23117fdd531..48662d42642 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,18 +1,16 @@ 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}; /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Hash(bound = ""))] +#[derive(TyEncodable, TyDecodable)] pub enum ClauseKind<I: Interner> { /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` @@ -161,65 +159,9 @@ where } } -impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ClauseKind<I> -where - I::Ty: Decodable<D>, - I::Const: Decodable<D>, - I::GenericArg: Decodable<D>, - I::TraitPredicate: Decodable<D>, - I::ProjectionPredicate: Decodable<D>, - I::TypeOutlivesPredicate: Decodable<D>, - I::RegionOutlivesPredicate: Decodable<D>, -{ - 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<I: Interner, E: TyEncoder> Encodable<E> for ClauseKind<I> -where - I::Ty: Encodable<E>, - I::Const: Encodable<E>, - I::GenericArg: Encodable<E>, - I::TraitPredicate: Encodable<E>, - I::ProjectionPredicate: Encodable<E>, - I::TypeOutlivesPredicate: Encodable<E>, - I::RegionOutlivesPredicate: Encodable<E>, -{ - 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 = ""))] +#[derive(TyEncodable, TyDecodable)] pub enum PredicateKind<I: Interner> { /// Prove a clause Clause(ClauseKind<I>), @@ -418,83 +360,6 @@ where } } -impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for PredicateKind<I> -where - I::DefId: Decodable<D>, - I::Const: Decodable<D>, - I::GenericArgs: Decodable<D>, - I::Term: Decodable<D>, - I::CoercePredicate: Decodable<D>, - I::SubtypePredicate: Decodable<D>, - I::ClosureKind: Decodable<D>, - ClauseKind<I>: Decodable<D>, -{ - 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<I: Interner, E: TyEncoder> Encodable<E> for PredicateKind<I> -where - I::DefId: Encodable<E>, - I::Const: Encodable<E>, - I::GenericArgs: Encodable<E>, - I::Term: Encodable<E>, - I::CoercePredicate: Encodable<E>, - I::SubtypePredicate: Encodable<E>, - I::ClosureKind: Encodable<E>, - ClauseKind<I>: Encodable<E>, -{ - 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)] pub enum AliasRelationDirection { diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 72f86fc0692..fc9eaf63ac8 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}; use std::fmt; -use crate::{ - DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, TyDecoder, - TyEncoder, WithInfcx, -}; +use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx}; use self::RegionKind::*; @@ -125,15 +121,23 @@ use self::RegionKind::*; Ord = "feature_allow_slow_enum", Hash(bound = "") )] +#[derive(TyEncodable, TyDecodable)] pub enum RegionKind<I: Interner> { /// 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), - /// 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 `ReFree` 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 @@ -163,7 +167,7 @@ pub enum RegionKind<I: Interner> { const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize { match value { ReEarlyBound(_) => 0, - ReLateBound(_, _) => 1, + ReBound(_, _) => 1, ReFree(_) => 2, ReStatic => 3, ReVar(_) => 4, @@ -192,7 +196,7 @@ impl<I: Interner> PartialEq for RegionKind<I> { 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, + (ReBound(a_d, a_r), ReBound(b_d, b_r)) => a_d == b_d && a_r == b_r, (ReFree(a_r), ReFree(b_r)) => a_r == b_r, (ReStatic, ReStatic) => true, (ReVar(a_r), ReVar(b_r)) => a_r == b_r, @@ -221,8 +225,8 @@ impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> { match this.data { ReEarlyBound(data) => write!(f, "ReEarlyBound({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:?}"), @@ -245,72 +249,6 @@ impl<I: Interner> fmt::Debug for RegionKind<I> { } } -// This is manually implemented because a derive would require `I: Encodable` -impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for RegionKind<I> -where - I::EarlyBoundRegion: Encodable<E>, - I::BoundRegion: Encodable<E>, - I::FreeRegion: Encodable<E>, - I::InferRegion: Encodable<E>, - I::PlaceholderRegion: Encodable<E>, -{ - 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<I: Interner, D: TyDecoder<I = I>> Decodable<D> for RegionKind<I> -where - I::EarlyBoundRegion: Decodable<D>, - I::BoundRegion: Decodable<D>, - I::FreeRegion: Decodable<D>, - I::InferRegion: Decodable<D>, - I::PlaceholderRegion: Decodable<D>, - I::ErrorGuaranteed: Decodable<D>, -{ - 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, - ) - ), - } - } -} - // This is not a derived impl because a derive would require `I: HashStable` impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I> where @@ -327,7 +265,7 @@ 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); } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 2138c273341..09a9a332269 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -2,14 +2,11 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; 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::*; @@ -122,6 +119,7 @@ pub enum AliasKind { Ord = "feature_allow_slow_enum", Hash(bound = "") )] +#[derive(TyEncodable, TyDecodable)] pub enum TyKind<I: Interner> { /// The primitive boolean type. Written as `bool`. Bool, @@ -472,178 +470,6 @@ impl<I: Interner> fmt::Debug for TyKind<I> { } } -// This is manually implemented because a derive would require `I: Encodable` -impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for TyKind<I> -where - I::ErrorGuaranteed: Encodable<E>, - I::AdtDef: Encodable<E>, - I::GenericArgs: Encodable<E>, - I::DefId: Encodable<E>, - I::Ty: Encodable<E>, - I::Const: Encodable<E>, - I::Region: Encodable<E>, - I::TypeAndMut: Encodable<E>, - I::PolyFnSig: Encodable<E>, - I::BoundExistentialPredicates: Encodable<E>, - I::Tys: Encodable<E>, - I::AliasTy: Encodable<E>, - I::ParamTy: Encodable<E>, - I::BoundTy: Encodable<E>, - I::PlaceholderTy: Encodable<E>, - I::InferTy: Encodable<E>, - I::AllocId: Encodable<E>, -{ - 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<I: Interner, D: TyDecoder<I = I>> Decodable<D> for TyKind<I> -where - I::ErrorGuaranteed: Decodable<D>, - I::AdtDef: Decodable<D>, - I::GenericArgs: Decodable<D>, - I::DefId: Decodable<D>, - I::Ty: Decodable<D>, - I::Const: Decodable<D>, - I::Region: Decodable<D>, - I::TypeAndMut: Decodable<D>, - I::PolyFnSig: Decodable<D>, - I::BoundExistentialPredicates: Decodable<D>, - I::Tys: Decodable<D>, - I::AliasTy: Decodable<D>, - I::ParamTy: Decodable<D>, - I::AliasTy: Decodable<D>, - I::BoundTy: Decodable<D>, - I::PlaceholderTy: Decodable<D>, - I::InferTy: Decodable<D>, - I::AllocId: Decodable<D>, -{ - 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<CTX: HashStableContext, I: Interner> HashStable<CTX> for TyKind<I> diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 4818bceadef..06933783685 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -437,9 +437,10 @@ pub enum BorrowKind { 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 { diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 5dfaa0fd891..d2f1f3af0ce 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -62,7 +62,7 @@ pub struct Region { #[derive(Clone, Debug, Eq, PartialEq)] pub enum RegionKind { ReEarlyBound(EarlyBoundRegion), - ReLateBound(DebruijnIndex, BoundRegion), + ReBound(DebruijnIndex, BoundRegion), ReStatic, RePlaceholder(Placeholder<BoundRegion>), ReErased, @@ -156,6 +156,7 @@ pub enum RigidTy { Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind), Never, Tuple(Vec<Ty>), + CoroutineWitness(CoroutineWitnessDef, GenericArgs), } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -235,6 +236,9 @@ pub struct ImplDef(pub DefId); #[derive(Clone, PartialEq, Eq, Debug)] pub struct RegionDef(pub DefId); +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct CoroutineWitnessDef(pub DefId); + /// A list of generic arguments. #[derive(Clone, Debug, Eq, PartialEq)] pub struct GenericArgs(pub Vec<GenericArgKind>); diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs index 05e0b9b4d78..65e42879d61 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 66fa91d4bad..e5df28a49af 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 = 116881 # ============================================================================= # Tweaking how LLVM is compiled @@ -42,11 +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. +# Set this to `"if-available"` if you are not sure whether you're on a tier 1 +# target. All tier 1 targets are currently supported; # # We also currently only support this when building LLVM for the build triple. # +# Set this to `"if-unchanged"` to only download if the llvm-project have not +# been modified. (If there are no changes or if built from tarball source, +# the logic is the same as "if-available") +# # 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 } @@ -553,10 +557,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 diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 1e2c35bf735..5b50ef7bf6c 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 4f0a02da440..f07c76232eb 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -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)] @@ -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 bd66ad61219..817b93720ce 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -305,10 +305,13 @@ impl<T, A: Allocator> RawVec<T, A> { /// 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<T, A: Allocator> RawVec<T, A> { 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/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6c78d65f1c9..ea7d6f6f4a6 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2706,7 +2706,7 @@ impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> { /// ``` /// use std::hash::BuildHasher; /// -/// let b = std::collections::hash_map::RandomState::new(); +/// let b = std::hash::RandomState::new(); /// let v: Vec<u8> = 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/tests/lib.rs b/library/alloc/tests/lib.rs index aa7a331b368..6d5c17ef023 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -43,8 +43,7 @@ #![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/core/src/array/mod.rs b/library/core/src/array/mod.rs index ebd4a8c05fe..9c8d7bbd999 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -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/convert/mod.rs b/library/core/src/convert/mod.rs index 89125b7955e..8c01b0973d6 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -138,7 +138,7 @@ pub const fn identity<T>(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<T: ?Sized> { /// /// [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 1170221c10c..f1a7ad93548 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<T>`` 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<T>` 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<T>`; in the case of `dyn Error` the aforementioned `request_ref` and ` diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 47db53ac6f3..4ccb585862c 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<F>(&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<F>(&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<F>(&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<F>(&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<F>(&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<F>(&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<F>(&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<F>(pub F) +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result; + +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +impl<F> fmt::Debug for FormatterFn<F> +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<F> fmt::Display for FormatterFn<F> +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 c45ab094a20..e1b7b46a1ed 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 4f42f73ebba..778515f8616 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 35b757dc1ee..153971a59c5 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<H: Hasher + ?Sized> 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 6b9f2e84257..78a232faaf8 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -14,7 +14,7 @@ use crate::ptr; /// /// See: <https://131002.net/siphash> #[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: <https://131002.net/siphash/> #[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<Sip24Rounds>, @@ -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/intrinsics.rs b/library/core/src/intrinsics.rs index 964aa3906f1..f855b2ad483 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1072,7 +1072,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 = "CURRENT_RUSTC_VERSION")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn assert_zero_valid<T>(); @@ -1080,7 +1080,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 = "CURRENT_RUSTC_VERSION")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn assert_mem_uninitialized_valid<T>(); diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index b26a17ec30e..0d8a306ace5 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 = { @@ -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<T>(place: T, goto: BasicBlock)); -define!("mir_call", fn Call(call: (), goto: BasicBlock)); +define!("mir_drop", fn Drop<T, U>(place: T, goto: BasicBlock, unwind_action: U)); +define!("mir_call", fn Call<U>(call: (), goto: BasicBlock, unwind_action: U)); +define!("mir_unwind_resume", + /// A terminator that resumes the unwinding. + fn UnwindResume() +); + define!("mir_storage_live", fn StorageLive<T>(local: T)); define!("mir_storage_dead", fn StorageDead<T>(local: T)); define!("mir_deinit", fn Deinit<T>(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 index 034ddd8df9a..fe25cac280f 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<usize> { - 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 00000000000..2f20180cdc9 --- /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/lib.rs b/library/core/src/lib.rs index de643fb333e..5a6d242a729 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -369,6 +369,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; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 125a6f57bfb..7f5908e477c 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 13437d8f961..99762bccd18 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -253,6 +253,7 @@ marker_impls! { /// /// const CFN: Wrap<fn(&())> = 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 855bb1675c5..8a4070ebd96 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -374,6 +374,9 @@ impl<T> MaybeUninit<T> { /// 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<T> MaybeUninit<T> { /// // 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 = "CURRENT_RUSTC_VERSION")] pub const fn zeroed() -> MaybeUninit<T> { let mut u = MaybeUninit::<T>::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 } diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 9159ecb740d..c964596dd5f 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -647,7 +647,8 @@ pub const fn needs_drop<T: ?Sized>() -> bool { #[allow(deprecated)] #[rustc_diagnostic_item = "mem_zeroed"] #[track_caller] -pub unsafe fn zeroed<T>() -> T { +#[rustc_const_stable(feature = "const_mem_zeroed", since = "CURRENT_RUSTC_VERSION")] +pub const unsafe fn zeroed<T>() -> T { // SAFETY: the caller must guarantee that an all-zero value is valid for `T`. unsafe { intrinsics::assert_zero_valid::<T>(); @@ -1357,6 +1358,7 @@ impl<T> SizedTypeProperties for T {} /// /// ``` /// #![feature(offset_of)] +/// # #![cfg_attr(not(bootstrap), feature(offset_of_enum))] /// /// use std::mem; /// #[repr(C)] diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index d6f2f5ca366..99adbb91599 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<Target = U>`, and `v` is a value of type `T`, then: /// -/// If `T` implements `Deref<Target = U>`, 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<T>`][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<T> Box<T>` 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<T>`][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<T: ?Sized> 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<Target = U>`, and `x` is a value of type `T`, +/// If `T` implements `DerefMut<Target = U>`, 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<T: ?Sized> 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/option.rs b/library/core/src/option.rs index acf3dfbdf4c..2303f289cdd 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1079,8 +1079,6 @@ impl<T> Option<T> { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// let v = vec![1, 2, 3, 4, 5]; /// /// // prints "got: 4" @@ -1090,11 +1088,8 @@ impl<T> Option<T> { /// let x: Option<&usize> = v.get(5).inspect(|x| println!("got: {x}")); /// ``` #[inline] - #[unstable(feature = "result_option_inspect", issue = "91345")] - pub fn inspect<F>(self, f: F) -> Self - where - F: FnOnce(&T), - { + #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] + pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self { if let Some(ref x) = self { f(x); } diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index f3695d16d7a..87e49210874 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::<char>(), Layout::new::<u32>()); +/// ``` /// /// [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 {} diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 84b179df8c1..fc4943c2aa9 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -505,6 +505,10 @@ pub unsafe fn drop_in_place<T: ?Sized>(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 +516,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(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 +531,10 @@ pub const fn null<T: ?Sized + Thin>() -> *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 +542,7 @@ pub const fn null<T: ?Sized + Thin>() -> *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] @@ -1911,8 +1921,7 @@ pub fn addr_eq<T: ?Sized, U: ?Sized>(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 +1998,18 @@ impl<F: FnPtr> 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 +2047,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/result.rs b/library/core/src/result.rs index 50127b27f8b..90c346e98bc 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -835,8 +835,6 @@ impl<T, E> Result<T, E> { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// let x: u8 = "4" /// .parse::<u8>() /// .inspect(|x| println!("original: {x}")) @@ -844,7 +842,7 @@ impl<T, E> Result<T, E> { /// .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<F: FnOnce(&T)>(self, f: F) -> Self { if let Ok(ref t) = self { f(t); @@ -858,8 +856,6 @@ impl<T, E> Result<T, E> { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// use std::{fs, io}; /// /// fn read() -> io::Result<String> { @@ -868,7 +864,7 @@ impl<T, E> Result<T, E> { /// } /// ``` #[inline] - #[unstable(feature = "result_option_inspect", issue = "91345")] + #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] pub fn inspect_err<F: FnOnce(&E)>(self, f: F) -> Self { if let Err(ref e) = self { f(e); diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 45080eda2ce..6cf5d48a167 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -640,6 +640,11 @@ impl<T> [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 +680,11 @@ impl<T> [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 /// diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index db76d26257a..993a608f42b 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/sync/atomic.rs b/library/core/src/sync/atomic.rs index b5ad3f280e6..f83f60857a2 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,16 +438,12 @@ impl AtomicBool { /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can /// be bigger than `align_of::<bool>()`). /// * `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 + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { @@ -1185,18 +1236,12 @@ impl<T> AtomicPtr<T> { /// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (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 + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> { @@ -2167,19 +2212,12 @@ 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 + /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index b63fd5c9095..817e39942c0 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/tests/fmt/num.rs b/library/core/tests/fmt/num.rs index b9ede65c9ff..1ddcd5ab795 100644 --- a/library/core/tests/fmt/num.rs +++ b/library/core/tests/fmt/num.rs @@ -128,28 +128,40 @@ 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 + + for i in i16::MIN..=i16::MAX { + 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 033bd1ed6ed..5268f32c031 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<Hasher = DefaultHasher> = &RandomState::new(); } diff --git a/library/std/src/io/readbuf/tests.rs b/library/core/tests/io/borrowed_buf.rs index 89a2f6b2271..69511e49acd 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 00000000000..a24893a525a --- /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 df7b34ce73b..c167240ba24 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -23,6 +23,7 @@ #![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)] @@ -135,6 +136,7 @@ mod fmt; mod future; mod hash; mod intrinsics; +mod io; mod iter; mod lazy; #[cfg(test)] @@ -167,7 +169,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::<Vec<u8>>(); diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 5c2e18745ea..20498b16cb2 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::<Foo>(); + + assert_eq!(unsafe { (*UNINIT.0.cast::<[[u8; SIZE]; 1]>())[0] }, [0u8; SIZE]); +} diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 2eb7608c7ae..f666b18887c 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/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 4d109285d16..39e94902cfe 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<K, V, S> HashMap<K, V, S> { /// /// ``` /// 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<K, V, S> HashMap<K, V, S> { /// /// ``` /// 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<K, V, S> HashMap<K, V, S> { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let hasher = RandomState::new(); /// let map: HashMap<i32, i32> = 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 91a3776e7be..8585376abc1 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 6a87f6e5f2d..8bc59608290 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<T, S> HashSet<T, S> { /// /// ``` /// 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<T, S> HashSet<T, S> { /// /// ``` /// 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<T, S> HashSet<T, S> { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let hasher = RandomState::new(); /// let set: HashSet<i32> = 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 e0cd80b44f8..208f61e755c 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 42f738acb9f..1389d24a8c5 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/hash/mod.rs b/library/std/src/hash/mod.rs new file mode 100644 index 00000000000..bd9bbf29875 --- /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: 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<H: Hasher>(&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: 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 00000000000..a1ccbb25369 --- /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/copy.rs b/library/std/src/io/copy.rs index 57d226a3771..4d51a719f6c 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -1,6 +1,7 @@ use super::{BorrowedBuf, BufReader, BufWriter, Read, Result, Write, DEFAULT_BUF_SIZE}; use crate::alloc::Allocator; use crate::cmp; +use crate::cmp::min; use crate::collections::VecDeque; use crate::io::IoSlice; use crate::mem::MaybeUninit; @@ -263,36 +264,67 @@ impl<A: Allocator> BufferedWriterSpec for Vec<u8, A> { fn copy_from<R: Read + ?Sized>(&mut self, reader: &mut R) -> Result<u64> { 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); + // avoid inflating empty/small vecs before we have determined that there's anything to read + if self.capacity() < DEFAULT_BUF_SIZE { + let stack_read_limit = DEFAULT_BUF_SIZE as u64; + bytes = stack_buffer_copy(&mut reader.take(stack_read_limit), self)?; + // fewer bytes than requested -> EOF reached + if bytes < stack_read_limit { + return Ok(bytes); } } + // don't immediately offer the vec's whole spare capacity, otherwise + // we might have to fully initialize it if the reader doesn't have a custom read_buf() impl + let mut max_read_size = DEFAULT_BUF_SIZE; + 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 mut initialized_spare_capacity = 0; - let read = buf.filled().len(); - if read == 0 { - break; - } + loop { + let buf = self.spare_capacity_mut(); + let read_size = min(max_read_size, buf.len()); + let mut buf = BorrowedBuf::from(&mut buf[..read_size]); + // SAFETY: init is either 0 or the init_len from the previous iteration. + unsafe { + buf.set_init(initialized_spare_capacity); + } + match reader.read_buf(buf.unfilled()) { + Ok(()) => { + let bytes_read = buf.len(); - // 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; - } + // EOF + if bytes_read == 0 { + return Ok(bytes); + } - Ok(bytes) + // the reader is returning short reads but it doesn't call ensure_init() + if buf.init_len() < buf.capacity() { + max_read_size = usize::MAX; + } + // the reader hasn't returned short reads so far + if bytes_read == buf.capacity() { + max_read_size *= 2; + } + + initialized_spare_capacity = buf.init_len() - bytes_read; + bytes += bytes_read as u64; + // 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() + bytes_read) }; + + // spare capacity full, reserve more + if self.len() == self.capacity() { + break; + } + } + Err(e) if e.is_interrupted() => continue, + Err(e) => return Err(e), + } + } + } } } diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index f438325560f..256b043a609 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -528,3 +528,17 @@ impl<A: Allocator> Write for VecDeque<u8, A> { Ok(()) } } + +#[unstable(feature = "read_buf", issue = "78485")] +impl<'a> io::Write for core::io::BorrowedCursor<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + 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 aa9a2482d2d..7d70a0bac24 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; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f57c8d4e7e2..f716c0fe922 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -310,6 +310,7 @@ // 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)] @@ -493,8 +494,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 +563,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; @@ -715,7 +715,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::<Vec<u8>>(); diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index f12ffbf2e01..dbc0f7d9df3 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: Hash>(t: T) -> u64 { let mut s = DefaultHasher::new(); diff --git a/library/std/tests/common/mod.rs b/library/std/tests/common/mod.rs index 358c2c3f9b2..1aad6549e76 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::<Vec<u8>>(); diff --git a/library/test/src/helpers/shuffle.rs b/library/test/src/helpers/shuffle.rs index ca503106c55..2ac3bfbd4d6 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<u64> { diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index bddf75dffbb..f92ffa94e99 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -264,8 +264,8 @@ pub fn run_tests<F>( 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<TestId, RunningTest, BuildHasherDefault<collections::hash_map::DefaultHasher>>; + type TestMap = HashMap<TestId, RunningTest, BuildHasherDefault<DefaultHasher>>; struct TimeoutEntry { id: TestId, diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index eab2717c452..9aa552ed81a 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -19,9 +19,6 @@ libc = { version = "0.2.79", features = ['rustc-dep-of-std'], default-features = compiler_builtins = "0.1.0" cfg-if = "1.0" -[build-dependencies] -cc = "1.0.76" - [features] # Only applies for Linux and Fuchsia targets diff --git a/library/unwind/build.rs b/library/unwind/build.rs deleted file mode 100644 index 5c3c02fb6ad..00000000000 --- 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 e86408a9ed2..335bded71c1 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -76,14 +76,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/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 346bfb30fec..57113b0ec62 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -181,16 +181,6 @@ dependencies = [ ] [[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" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -324,15 +314,6 @@ 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" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -444,16 +425,6 @@ dependencies = [ ] [[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" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -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/bootstrap.py b/src/bootstrap/bootstrap.py index 1a1125a107f..5a84e37f8cf 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 @@ -681,7 +681,7 @@ class RustBuild(object): 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 +727,7 @@ class RustBuild(object): "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 +747,7 @@ class RustBuild(object): 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): @@ -1005,7 +1005,7 @@ class RustBuild(object): 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 +1017,14 @@ class RustBuild(object): "--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): @@ -1125,7 +1125,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 e6caabec4f6..6da410ed2f2 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 626ca6cf2e7..544a42d9ada 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 113df88d7c3..7c33ce958c9 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/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index ffc38057900..9998fe2f5db 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 d87fb6a9cef..0a6072ae1a5 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -63,7 +63,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 +76,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 +97,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"); } } @@ -109,31 +109,35 @@ fn check_version(config: &Config) -> Option<String> { } let latest_config_id = CONFIG_CHANGE_HISTORY.last().unwrap(); - let suggestion = if let Some(id) = config.change_id { - if &id != latest_config_id { + if let Some(id) = config.change_id { + if &id == latest_config_id { + return None; + } + + let change_links: Vec<String> = 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("WARNING: there have been changes to x.py since you last updated.\n"); - let change_links: Vec<String> = 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("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 { - return None; + + msg.push_str("NOTE: to silence this warning, "); + msg.push_str(&format!( + "update `config.toml` to use `change-id = {latest_config_id}` instead" + )); } } 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_config_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 3041fd37ac8..070a2da6afb 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -32,6 +32,9 @@ fn main() { let args = env::args_os().skip(1).collect::<Vec<_>>(); let arg = |name| 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 @@ -242,7 +245,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/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 121925b56a0..d36c41906b0 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") } } } diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index 679770ce0ec..cbb6b5f4648 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,6 @@ 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("rustfmt.stamp")); for host in &build.hosts { @@ -178,7 +183,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 1eed534150b..7021a954358 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") { @@ -822,8 +817,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; } @@ -1208,8 +1203,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 +1250,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 +1525,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 +1545,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, @@ -1991,7 +1986,7 @@ pub fn stream_cargo( builder.verbose(&format!("running: {cargo:?}")); 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 +2050,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 b578c5ec295..c485481b9a1 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<GeneratedTarball> { + 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 628a4ece8e9..e3fd942fc38 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -685,19 +685,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 +711,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 +724,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 +765,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 +821,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 +837,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 +853,69 @@ 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-platform", - "-p", "cargo-util", - "-p", "crates-io", - "-p", "cargo-test-macro", - "-p", "cargo-test-support", - "-p", "cargo-credential", - "-p", "mdman", // FIXME: this trips a license check in tidy. - // "-p", // "resolver-tests", ] ); -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 0e260e69c85..86f1d925f73 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<Option<Vec<String>>, 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)] diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 9d03350c723..6b4a8f597ea 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 5b454307721..a1f6fac8a51 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -132,8 +132,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 +156,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!(); } diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 435ebb6df90..486a1e20f18 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -122,6 +122,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 +168,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 +212,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,19 +225,6 @@ 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 settings = format!( @@ -397,8 +414,8 @@ pub fn interactive_path() -> io::Result<Profile> { 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 +444,8 @@ fn prompt_user(prompt: &str) -> io::Result<Option<PromptResult>> { "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 +486,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 +504,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 ); @@ -556,10 +578,10 @@ 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" ), _ => (), } @@ -586,7 +608,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" } diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs index 82fb10cebe0..93da27560c6 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 e2b515a3086..254fbc72a8c 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -369,7 +369,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 +378,7 @@ impl Step for RustAnalyzer { let mut cargo = tool::prepare_tool_cargo( builder, compiler, - Mode::ToolStd, + Mode::ToolRustc, host, "test", crate_path, @@ -1127,10 +1127,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, ); @@ -1183,7 +1183,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 +1305,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 +1390,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. @@ -1472,10 +1566,10 @@ impl Step for Compiletest { fn run(self, builder: &Builder<'_>) { 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 +1640,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 +1662,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 @@ -1760,11 +1854,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() @@ -1877,6 +1971,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")] diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index d5f759ea159..e8327b751d3 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -422,7 +422,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 +454,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 +603,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 +635,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 +786,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 <tool>` 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 f892577ccbf..a451f92b6bc 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 44cdbe38de3..cd276674dee 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -386,13 +386,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); } @@ -727,8 +727,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 +740,7 @@ impl<'a> Builder<'a> { test::CodegenCranelift, test::CodegenGCC, test::Rustdoc, - test::RunCoverageRustdoc, + test::CoverageRunRustdoc, test::Pretty, test::Crate, test::CrateLibrustc, @@ -1359,9 +1360,9 @@ impl<'a> Builder<'a> { } }).unwrap_or_else(|_| { eprintln!( - "error: `x.py clippy` requires a host `rustc` toolchain with the `clippy` component" + "ERROR: `x.py clippy` requires a host `rustc` toolchain with the `clippy` component" ); - eprintln!("help: try `rustup component add clippy`"); + eprintln!("HELP: try `rustup component add clippy`"); crate::exit!(1); }); if !t!(std::str::from_utf8(&output.stdout)).contains("nightly") { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index f56e46010f3..0a9175aa3ea 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -19,6 +19,7 @@ use std::process::Command; use std::str::FromStr; 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}; @@ -30,6 +31,7 @@ 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) => { @@ -318,6 +320,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)] @@ -1072,6 +1075,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 +1433,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); @@ -1458,7 +1464,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 +1533,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 +1808,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:?}"); @@ -2006,6 +2002,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 +2073,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 +2090,108 @@ 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<StringOrBool>, + asserts: bool, + ) -> bool { + match download_ci_llvm { + None => self.channel == "dev" && llvm::is_ci_llvm_available(&self, asserts), + Some(StringOrBool::Bool(b)) => b, + 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<String> { + // 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<T>(field: &mut T, val: Option<T>) { diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 64af114f998..2a301007ab4 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 5541a2f3e35..3327aed9600 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -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 } @@ -606,10 +606,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 +685,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 d7f49a6d11b..33b8f1a7ce7 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -75,9 +75,10 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; /// 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]; +/// 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. +/// This is necessary because the list must be sorted by the merge date. +pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998, 117435, 116881]; /// Extra --check-cfg to add when building /// (Mode restriction, config name, config values (if any)) @@ -1197,11 +1198,10 @@ impl Build { .filter(|s| !s.starts_with("-O") && !s.starts_with("/O")) .collect::<Vec<String>>(); - // 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 +1568,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 +1697,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); @@ -1850,10 +1850,21 @@ fn envify(s: &str) -> String { } pub fn find_recent_config_change_ids(current_id: usize) -> Vec<usize> { - let index = CONFIG_CHANGE_HISTORY - .iter() - .position(|&id| id == current_id) - .expect(&format!("Value `{}` was not found in `CONFIG_CHANGE_HISTORY`.", current_id)); + if !CONFIG_CHANGE_HISTORY.contains(¤t_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(max_id) = CONFIG_CHANGE_HISTORY.iter().max() { + if ¤t_id > max_id { + return Vec::new(); + } + } + + return CONFIG_CHANGE_HISTORY.to_vec(); + } + + let index = CONFIG_CHANGE_HISTORY.iter().position(|&id| id == current_id).unwrap(); CONFIG_CHANGE_HISTORY .iter() diff --git a/src/bootstrap/src/utils/bin_helpers.rs b/src/bootstrap/src/utils/bin_helpers.rs index b9177c490ac..c90fd2805e2 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/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 82a5607d903..5bc81f2d983 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -233,7 +233,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 +262,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 +327,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) } } diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs index 65794f05d2d..174f374224c 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::<JsonRoot>(&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/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index f97aa958513..bff47f65c51 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/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh index 56ee348a337..1d9568702cc 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 3b3ec5da74b..e939a5d7eac 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/run.sh b/src/ci/docker/run.sh index a2891ef9563..cedbc0390f8 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -302,6 +302,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 f78d446c8b7..437b51641fc 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -12,6 +12,7 @@ from dataclasses import dataclass import fcntl import glob import hashlib +import io import json import os import platform @@ -276,27 +277,60 @@ class TestEnvironment: 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 b415eb5961b..da29ffb8e5f 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 @@ -565,6 +569,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 31ef55216b9..ce0dd6018af 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" diff --git a/src/ci/scripts/install-tidy.sh b/src/ci/scripts/install-tidy.sh new file mode 100755 index 00000000000..fab126453fd --- /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/reference b/src/doc/reference -Subproject 16fd3c06d9e558dae2d52000818274ae70c9e90 +Subproject cd8193e972f61b92117095fc73b67af767b4d6b diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject 6709beeb7d0fbc5ffc91ac4893a24434123b9bf +Subproject 311b84962016b28c75525c86e7b3f49fd9101a3 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject b0ee9ec8fa59a6c7620165e061f4747202377a6 +Subproject 77dbe5782b2488af3bb489ad702eaff438f465b diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 8b4d673d831..1b27b77b3e6 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -41,6 +41,7 @@ - [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) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md index 172048704f4..d4e2fc52e97 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.<sup id="fnref:1" role="doc-noteref"><a -href="#fn:1" class="footnote">1</a></sup> +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.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" +class="footnote">1</a></sup> 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`<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" +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`<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote">2</a></sup>. -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. -<small id="fn:2">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). <a href="#fnref:2" -class="reversefootnote" role="doc-backlink">↩</a></small> +<small id="fn:2">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). <a href="#fnref:2" class="reversefootnote" +role="doc-backlink">↩</a></small> ### Non-executable memory regions @@ -158,17 +159,16 @@ class="reversefootnote" role="doc-backlink">↩</a></small> 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 regions<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" +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 +regions<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote">3</a></sup> 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">↩</a></small> 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]. - -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. + +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. - -Fig. 8. IDA Pro listing cross references to `__rust_probestack` 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` flag<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" -class="footnote">4</a></sup> 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</a></sup> 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). <small id="fn:4">4\. And the `DF_1_NOW` flag for some link editors. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">↩</a></small> @@ -287,26 +287,24 @@ href="#fnref:4" class="reversefootnote" role="doc-backlink">↩</a></small> ### 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 allocator<sup id="fnref:5" role="doc-noteref"><a -href="#fn:5" class="footnote">5</a></sup> 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 allocator<sup id="fnref:5" role="doc-noteref"><a href="#fn:5" +class="footnote">5</a></sup> 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). <small id="fn:5">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. <a href="#fnref:5" class="reversefootnote" -role="doc-backlink">↩</a></small> +Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram Gloger, +which in turn is derived from dlmalloc (Doug Lea malloc) by Doug Lea. <a +href="#fnref:5" class="reversefootnote" role="doc-backlink">↩</a></small> ### 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].  -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] <sup id="fnref:6" role="doc-noteref"><a href="#fn:6" +builds[41]-[42] <sup id="fnref:6" role="doc-noteref"><a href="#fn:6" class="footnote">6</a></sup>. ```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">↩</a></small> ### 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 -<sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote">7</a></sup> -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 architecture<sup +id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote">7</a></sup>on +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). -<small id="fn:7">7\. The shadow stack implementation for the AMD64 -architecture and equivalent in LLVM was removed due to performance and -security issues. <a href="#fnref:7" class="reversefootnote" -role="doc-backlink">↩</a></small> +<small id="fn:7">7\. The shadow stack implementation for the AMD64 architecture +and equivalent in LLVM was removed due to performance and security issues. <a +href="#fnref:7" class="reversefootnote" role="doc-backlink">↩</a></small> ## Appendix @@ -470,29 +457,28 @@ role="doc-backlink">↩</a></small> 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. <https://github.com/rust-lang/rust/pull/30859>. -26. “Replace stack overflow checking with stack probes #16012.” GitHub. +26. Zoxc. “Replace stack overflow checking with stack probes #16012.” GitHub. <https://github.com/rust-lang/rust/issues/16012>. -27. B. Striegel. “Extend stack probe support to non-tier-1 platforms, and - clarify policy for mitigating LLVM-dependent unsafety #43241.” GitHub. - <https://github.com/rust-lang/rust/issues/43241>. - -28. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub. +27. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub. <https://github.com/rust-lang/rust/pull/42816>. -29. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub. +28. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub. <https://github.com/rust-lang/compiler-builtins/pull/175>. +29. S. Guelton, S. Ledru, J. Stone. “Bringing Stack Clash Protection to Clang / + X86 — the Open Source Way.” The LLVM Project Blog. + <https://blog.llvm.org/posts/2021-01-05-stack-clash-protection/>. + 30. B. Anderson. “Consider applying -Wl,-z,relro or -Wl,-z,relro,-z,now by default #29877.” GitHub. <https://github.com/rust-lang/rust/issues/29877>. @@ -621,16 +607,16 @@ defaults (unrelated to `READ_IMPLIES_EXEC`). 39. A. Crichton. “Remove the alloc\_jemalloc crate #55238.” GitHub. <https://github.com/rust-lang/rust/pull/55238>. -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. <https://github.com/rust-lang/rust/pull/84197> + +41. R. de C. Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support for Rust #89653.” GitHub. <https://github.com/rust-lang/rust/issues/89653>. -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. <https://github.com/rust-lang/rust/pull/84197> - -43. ivanloz. “Add support for LLVM ShadowCallStack. #98208.” GitHub. +43. I. Lozano. “Add support for LLVM ShadowCallStack #98208.” GitHub. <https://github.com/rust-lang/rust/pull/98208>. 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 ee2d3fd4f43..0da45e56620 100644 --- a/src/doc/rustc/src/images/image1.png +++ b/src/doc/rustc/src/images/image1.png Binary files differdiff --git a/src/doc/rustc/src/images/image2.png b/src/doc/rustc/src/images/image2.png index 03061e1f0b1..a9cf23f8737 100644 --- a/src/doc/rustc/src/images/image2.png +++ b/src/doc/rustc/src/images/image2.png Binary files differdiff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png index ef02c605ead..844a2fe6747 100644 --- a/src/doc/rustc/src/images/image3.png +++ b/src/doc/rustc/src/images/image3.png Binary files differdiff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 6a979869a59..907e9c59f31 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -310,7 +310,7 @@ 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) 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 00000000000..c3ce71a1835 --- /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/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index f7cce35b123..34ab3cdaf25 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/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index bdf6a0f6b23..eb946e82f39 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -743,7 +743,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> 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::ReEarlyBound(_) | ty::ReStatic | ty::ReBound(..) | ty::ReError(_) => r, r => bug!("unexpected region: {r:?}"), } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 013814b1f7d..974ba1e3bd9 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -599,7 +599,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), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e6e2d60f2e5..d33e41dc2b3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -286,11 +286,9 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Life match *region { ty::ReStatic => Some(Lifetime::statik()), _ if !region.has_name() => None, - ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => { - Some(Lifetime(name)) - } + ty::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => Some(Lifetime(name)), ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)), - ty::ReLateBound(..) + ty::ReBound(..) | ty::ReFree(..) | ty::ReVar(..) | ty::ReError(_) @@ -1931,13 +1929,11 @@ fn clean_trait_object_lifetime_bound<'tcx>( 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::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) if name != kw::Empty => { Some(Lifetime(name)) } ty::ReEarlyBound(_) - | ty::ReLateBound(..) + | ty::ReBound(..) | ty::ReFree(_) | ty::ReVar(_) | ty::RePlaceholder(_) @@ -2534,7 +2530,8 @@ 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 `<true>` for non-const impls of const traits + // Checking for `#[rustc_host]` 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(ct) if cx.tcx.has_attr(ct.value.def_id, sym::rustc_host) => { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a718cb37d89..88ee4e3a2ab 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1327,6 +1327,7 @@ impl WherePredicate { pub(crate) enum GenericParamDefKind { Lifetime { outlives: ThinVec<Lifetime> }, Type { did: DefId, bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool }, + // Option<Box<String>> makes this type smaller than `Option<String>` would. Const { ty: Box<Type>, default: Option<Box<String>>, is_host_effect: bool }, } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index dea7bfaf7e2..9ff00c1946f 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; } @@ -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. diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 3e58dd96ed9..d2c7c578c08 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -356,15 +356,12 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; let content = format!( "<h1>List of all crates</h1><ul class=\"all-items\">{}</ul>", - krates - .iter() - .map(|s| { - format!( - "<li><a href=\"{trailing_slash}index.html\">{s}</a></li>", - trailing_slash = ensure_trailing_slash(s), - ) - }) - .collect::<String>() + krates.iter().format_with("", |k, f| { + f(&format_args!( + "<li><a href=\"{trailing_slash}index.html\">{k}</a></li>", + 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/static/js/main.js b/src/librustdoc/html/static/js/main.js index 7c052606aba..615fb08c76f 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -54,7 +54,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 +485,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 = `<a href="${modpath}index.html#${id}">${longty}</a>`; diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index ebf817673bf..3f6147bb916 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -10,7 +10,6 @@ <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_regular}}"> {# #} <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_medium}}"> {# #} <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_regular}}"> {# #} - <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_bold}}"> {# #} <link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_semibold}}"> {# #} <link rel="stylesheet" {#+ #} href="{{static_root_path|safe}}{{files.normalize_css}}"> {# #} diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index b8b7785a2a1..c75fc34a9df 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -54,7 +54,7 @@ <strong>Note:</strong> Encountered an error during type layout; {#+ #} the type failed to be normalized. {# #} </p> {# #} - {% when Err(LayoutError::Cycle) %} + {% when Err(LayoutError::Cycle(_)) %} <p> {# #} <strong>Note:</strong> Encountered an error during type layout; {#+ #} the type's layout depended on the type's layout itself. {# #} diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 0c15bf5f764..472781e7d22 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/llvm-project b/src/llvm-project -Subproject fef3d7b14ede45d051dc688aae0bb8c8b02a056 +Subproject 7738295178045041669876bf32b0543ec8319a5 diff --git a/src/stage0.json b/src/stage0.json index 32dc8a2f83c..2b39e1b1158 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": [ diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 2c795ebb214..aed6796fa13 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -266,6 +266,29 @@ impl Builder { // channel-rust-1.XX.toml let major_minor = rust_version.split('.').take(2).collect::<Vec<_>>().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::<Vec<_>>().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::<Vec<_>>().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 f20b7a2b4d7..b91dc38e924 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<String, String> { let output = match cmd.stderr(Stdio::inherit()).output() { @@ -27,7 +32,10 @@ fn output_result(cmd: &mut Command) -> Result<String, String> { /// 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<String, String> { +pub fn get_rust_lang_rust_remote( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result<String, String> { 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<String, Strin let rust_lang_remote = stdout .lines() - .find(|remote| remote.contains("rust-lang")) - .ok_or_else(|| "rust-lang/rust remote not found".to_owned())?; + .find(|remote| remote.contains(config.git_repository)) + .ok_or_else(|| format!("{} remote not found", config.git_repository))?; let remote_name = rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?; @@ -76,9 +84,13 @@ pub fn rev_exists(rev: &str, git_dir: Option<&Path>) -> Result<bool, String> { /// 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<String, String> { - 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<String, String> { + 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<String, String> { Err(format!("Cannot find any suitable upstream master branch")) } -pub fn get_git_merge_base(git_dir: Option<&Path>) -> Result<String, String> { - let updated_master = updated_master_branch(git_dir)?; +pub fn get_git_merge_base( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result<String, String> { + 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<String, String> { /// 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<Option<Vec<String>>, 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<Option<Vec<String>>, String> { - let Ok(_updated_master) = updated_master_branch(git_dir) else { +pub fn get_git_untracked_files( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result<Option<Vec<String>>, 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/cargo b/src/tools/cargo -Subproject b4d18d4bd3db6d872892f6c87c51a02999b8080 +Subproject 6790a5127895debec95c24aefaeb18e059270df diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index fad8fbf0449..02c53fafd69 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -247,8 +247,8 @@ 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/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 4d7a055dae1..d6fa742b796 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 @@ -168,7 +168,7 @@ 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; diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 83863b92caf..c6ac96a4539 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -466,7 +466,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( .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::ReBound(_, r) => r.kind.get_id(), ty::ReFree(r) => r.bound_region.get_id(), ty::ReStatic | ty::ReVar(_) diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index ce93aea2136..152248afc90 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, Closure, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, CaptureBy }; 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); }, diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 7eff93881b2..2ff979f2dcb 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -890,7 +890,7 @@ pub fn for_each_top_level_late_bound_region<B>( impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow<B>> TypeVisitor<TyCtxt<'tcx>> for V<F> { type BreakTy = B; fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> { - 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,7 +1160,7 @@ pub fn make_normalized_projection<'tcx>( ) -> Option<Ty<'tcx>> { fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> { #[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_bound_regions()) { debug_assert!( false, "args contain late-bound region at index `{i}` which can't be normalized.\n\ @@ -1233,7 +1233,7 @@ pub fn make_normalized_projection_with_regions<'tcx>( ) -> Option<Ty<'tcx>> { fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option<Ty<'tcx>> { #[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_bound_regions()) { debug_assert!( false, "args contain late-bound region at index `{i}` which can't be normalized.\n\ diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout index eb3e5189c82..140300a1673 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/match_same_arms_non_exhaustive.rs b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs index e1b95aa5776..5c277f925a8 100644 --- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs +++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs @@ -9,12 +9,12 @@ fn repeat() -> ! { } pub fn f(x: Ordering) { + #[deny(non_exhaustive_omitted_patterns)] match x { Ordering::Relaxed => println!("relaxed"), Ordering::Release => println!("release"), Ordering::Acquire => println!("acquire"), Ordering::AcqRel | Ordering::SeqCst => repeat(), - #[deny(non_exhaustive_omitted_patterns)] _ => repeat(), } } diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 0e1bf0c6c2d..1e9684555f1 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! { @@ -370,6 +380,10 @@ pub struct Config { pub target_cfgs: AtomicLazyCell<TargetCfgs>, pub nocapture: bool, + + // Needed both to construct build_helper::git::GitConfig + pub git_repository: String, + pub nightly_branch: String, } impl Config { @@ -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 948439d6e79..d6516cff63f 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -911,11 +911,11 @@ pub fn make_test_description<R: Read>( 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/tests.rs b/src/tools/compiletest/src/header/tests.rs index 2fd80b52cee..85e745bed11 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<String> = args.iter().map(ToString::to_string).collect(); diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 619ff9b3221..bb09c03ef5b 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -144,7 +144,9 @@ pub fn parse_config(args: Vec<String>) -> 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" { @@ -307,6 +309,9 @@ pub fn parse_config(args: Vec<String>) -> 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 +614,10 @@ fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, 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 e74d66a8599..8854908c430 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(), } } @@ -510,7 +509,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 +548,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 +2192,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 +2394,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 +2477,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 +2719,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`. @@ -3962,7 +3961,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, 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 d47af50d407..e79bd70e915 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 381442e69b1..ccf9732ed07 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,8 +27,8 @@ 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 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 3d8ba68547b..e7baf6e23db 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,8 +35,8 @@ 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 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 ea773048dd4..e4c00fdd845 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_during.none.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr index cba23c21d12..f8140d0236a 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,8 +11,8 @@ 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 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 8c6a7df7a6d..517abd733a9 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 f8532186be2..c37e788e6b4 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,8 +27,8 @@ 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 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 7b1846a32db..7557d3710d1 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,8 +35,8 @@ 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 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 0a31adabf73..dd951066c32 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,8 +11,8 @@ 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 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 3d560af3d5e..23b1e38b99f 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 875cc5edad9..cf13be6da01 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,8 +27,8 @@ 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 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 deafbf02077..e16c4c0ebb6 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,8 +35,8 @@ 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 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 c1bbc748e1a..56706cdb63b 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 0666db34fec..5d76d9eab67 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,8 +30,8 @@ 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 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 e1b40a6bc18..e8165a73ff4 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,8 +35,8 @@ 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 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 79e29b79d6a..923c59e7429 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/validity/cast_fn_ptr_invalid_caller_arg.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs index ee80186d4b5..9357b372505 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 234c2804008..b40d99f7bc9 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 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 d410a875b1b..89ee689fabe 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/rust-analyzer/.github/workflows/autopublish.yaml b/src/tools/rust-analyzer/.github/workflows/autopublish.yaml index 310a8a5be7a..9a5015005b3 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 fb7b4b07f98..1f2a7796d11 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 bbeccd1621d..741e559953f 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/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index bd6554bf889..fcb188c0dfa 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -33,12 +33,6 @@ 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" - -[[package]] name = "arbitrary" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -177,9 +171,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chalk-derive" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff5053a8a42dbff5279a82423946fc56dc1253b76cf211b2b3c14b3aad4e1281" +checksum = "264726159011fc7f22c23eb51f49021ece6e71bc358b96e7f2e842db0b14162b" dependencies = [ "proc-macro2", "quote", @@ -189,9 +183,9 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56de2146a8ed0fcd54f4bd50db852f1de4eac9e1efe568494f106c21b77d2a" +checksum = "d65c17407d4c756b8f7f84344acb0fb96364d0298822743219bb25769b6d00df" dependencies = [ "bitflags 1.3.2", "chalk-derive", @@ -200,9 +194,9 @@ dependencies = [ [[package]] name = "chalk-recursive" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc09e6e9531f3544989ef89b189e80fbc7ad9e2f73f1c5e03ddc9ffb0527463" +checksum = "80e2cf7b70bedaaf3a8cf3c93b6120c2bb65be89389124028e724d19e209686e" dependencies = [ "chalk-derive", "chalk-ir", @@ -213,9 +207,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.92.0" +version = "0.93.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b392e02b4c81ec76d3748da839fc70a5539b83d27c9030668463d34d5110b860" +checksum = "afc67c548d3854f64e97e67dc5b7c88513425c5bfa347cff96b7992ae6379288" dependencies = [ "chalk-derive", "chalk-ir", @@ -518,7 +512,6 @@ dependencies = [ name = "hir-def" version = "0.0.0" dependencies = [ - "anymap", "arrayvec", "base-db", "bitflags 2.3.2", @@ -531,8 +524,6 @@ dependencies = [ "fst", "hashbrown 0.12.3", "hir-expand", - "hkalbasi-rustc-ap-rustc_abi", - "hkalbasi-rustc-ap-rustc_index", "indexmap 2.0.0", "intern", "itertools", @@ -541,7 +532,7 @@ dependencies = [ "mbe", "once_cell", "profile", - "ra-ap-rustc_parse_format", + "rustc-dependencies", "rustc-hash", "smallvec", "stdx", @@ -594,7 +585,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 +594,7 @@ dependencies = [ "oorandom", "profile", "project-model", + "rustc-dependencies", "rustc-hash", "scoped-tls", "smallvec", @@ -618,27 +609,6 @@ dependencies = [ ] [[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" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -918,9 +888,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libloading" @@ -1277,7 +1247,7 @@ dependencies = [ "drop_bomb", "expect-test", "limit", - "ra-ap-rustc_lexer", + "rustc-dependencies", "sourcegen", "stdx", ] @@ -1435,9 +1405,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 +1416,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", ] @@ -1483,20 +1453,51 @@ dependencies = [ ] [[package]] +name = "ra-ap-rustc_abi" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7082716cb2bbcd8b5f062fe950cbbc87f3aba022d6da4168db35af6732a7f15d" +dependencies = [ + "bitflags 1.3.2", + "ra-ap-rustc_index 0.18.0", + "tracing", +] + +[[package]] name = "ra-ap-rustc_index" -version = "0.10.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b5fa61d34da18e148dc3a81f654488ea07f40938d8aefb17f8b64bb78c6120" +checksum = "643ca3609870b1778d9cd1f2a8e4ccb4af0f48f3637cc257a09494d087bd93dc" dependencies = [ "arrayvec", "smallvec", ] [[package]] +name = "ra-ap-rustc_index" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e14b1fc835d6992b128a03a3f3a8365ba9f03e1c656a1670305f63f30d786d" +dependencies = [ + "arrayvec", + "smallvec", +] + +[[package]] +name = "ra-ap-rustc_lexer" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ffd24f9ba4f1d25ff27ca1469b8d22a3bdfb12cf644fc8bfcb63121fa5da6b" +dependencies = [ + "unicode-properties", + "unicode-xid", +] + +[[package]] name = "ra-ap-rustc_lexer" -version = "0.10.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e2f6b48422e4eed5218277ab7cc9733e60dd8f3167f4f36a49a0cafe4dc195" +checksum = "1762abb25eb1e37c1823f62b5da0821bbcd870812318db084c9516c2f78d2dcd" dependencies = [ "unicode-properties", "unicode-xid", @@ -1504,12 +1505,12 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.10.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7369ad01cc79f9e3513c9f6a6326f6b980100e4862a7ac71b9991c88108bb" +checksum = "207b5ac1a21d4926695e03b605ffb9f63d4968e0488e9197c04c512c37303aa7" dependencies = [ - "ra-ap-rustc_index", - "ra-ap-rustc_lexer", + "ra-ap-rustc_index 0.14.0", + "ra-ap-rustc_lexer 0.14.0", ] [[package]] @@ -1594,10 +1595,12 @@ dependencies = [ "oorandom", "parking_lot 0.12.1", "parking_lot_core 0.9.6", + "parser", "proc-macro-api", "profile", "project-model", "rayon", + "rustc-dependencies", "rustc-hash", "scip", "serde", @@ -1627,6 +1630,16 @@ 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 0.18.0", + "ra-ap-rustc_lexer 0.18.0", + "ra-ap-rustc_parse_format", +] + +[[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1678,9 +1691,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", ] @@ -1853,9 +1866,9 @@ dependencies = [ "proc-macro2", "profile", "quote", - "ra-ap-rustc_lexer", "rayon", "rowan", + "rustc-dependencies", "rustc-hash", "smol_str", "sourcegen", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index cab88fc18ce..c382a5a37d2 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" } @@ -101,11 +102,6 @@ serde = { version = "1.0.156", features = ["derive"] } serde_json = "1.0.96" triomphe = { version = "0.1.8", 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 } 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 b75c7079be7..65db5c0fc7d 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -257,6 +257,7 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe { ) -> Result<Subtree, ProcMacroExpansionError>; } +#[derive(Debug)] pub enum ProcMacroExpansionError { Panic(String), /// Things like "proc macro server was killed by OOM". 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 af204e44e6e..c5c4afa30f7 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -75,7 +75,7 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug { #[salsa::input] fn crate_graph(&self) -> Arc<CrateGraph>; - /// The crate graph. + /// The proc macros. #[salsa::input] fn proc_macros(&self) -> Arc<ProcMacros>; } diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs index 2de719af92c..0749d91eb32 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<String>, extra_env: FxHashMap<String, String>, ansi_color_output: bool, + target_dir: Option<PathBuf>, }, 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 8cf61ee04d4..99b8e9bf0e1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml @@ -12,7 +12,6 @@ rust-version.workspace = true doctest = false [dependencies] -anymap = "1.0.0-beta.2" arrayvec = "0.7.2" bitflags = "2.1.0" cov-mark = "2.0.0-pre.1" @@ -31,10 +30,7 @@ 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 c6454eb9ea0..fa3025e0303 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/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index c0baf6011f7..1942c60c075 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<ast::Expr>; pub type ExprSource = InFile<ExprPtr>; -pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>; +pub type PatPtr = AstPtr<Either<ast::Pat, ast::SelfParam>>; pub type PatSource = InFile<PatPtr>; pub type LabelPtr = AstPtr<ast::Label>; @@ -356,12 +356,12 @@ impl BodySourceMap { } pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> { - 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<PatId> { - 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 cc02df80a8f..e4158d7564b 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<Binding> = 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<Binding> = + 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<ast::Pat>, binding_list: &mut BindingList) -> PatId { 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 2a90a09f25e..baca293e290 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<ScopeData>; pub struct ExprScopes { scopes: Arena<ScopeData>, scope_entries: Arena<ScopeEntry>, - scope_by_expr: FxHashMap<ExprId, ScopeId>, + scope_by_expr: ArenaMap<ExprId, ScopeId>, } #[derive(Debug, PartialEq, Eq)] @@ -77,10 +76,10 @@ impl ExprScopes { } pub fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { - self.scope_by_expr.get(&expr).copied() + self.scope_by_expr.get(expr).copied() } - pub fn scope_by_expr(&self) -> &FxHashMap<ExprId, ScopeId> { + pub fn scope_by_expr(&self) -> &ArenaMap<ExprId, ScopeId> { &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 68defa3858f..718f241cf78 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, @@ -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()), 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 224f7328f8c..b163112db91 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 63138aa6ad7..a59bbf7e221 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<K, V, P = (K, V)> { _phantom: PhantomData<(K, V, P)>, 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 75025a984fc..46d24bd4a61 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 44b7f1b4f63..c0b507d3911 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,7 +1,6 @@ //! A map of all publicly exported items in a crate. -use std::collections::hash_map::Entry; -use std::{fmt, hash::BuildHasherDefault}; +use std::{collections::hash_map::Entry, fmt, hash::BuildHasherDefault}; use base_db::CrateId; use fst::{self, Streamer}; @@ -11,10 +10,12 @@ use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; 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<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>; @@ -94,7 +95,7 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap<ItemIn // We look only into modules that are public(ly reexported), starting with the crate root. let root = def_map.module_id(DefMap::ROOT); - let mut worklist = vec![(root, 0)]; + let mut worklist = vec![(root, 0u32)]; // Records items' minimum module depth. let mut depth_map = FxHashMap::default(); @@ -278,6 +279,8 @@ enum SearchMode { /// 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 +322,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 } @@ -356,7 +367,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() { 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 4c812b62a46..3c4f21d5c69 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 @@ -613,10 +613,17 @@ pub struct Function { pub(crate) flags: FnFlags, } -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Param { - Normal(Interned<TypeRef>), - Varargs, +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Param { + /// This is [`None`] for varargs + pub type_ref: Option<Interned<TypeRef>>, + pub ast_id: ParamAstId, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ParamAstId { + Param(FileAstId<ast::Param>), + SelfParam(FileAstId<ast::SelfParam>), } bitflags::bitflags! { 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 e4702c113b8..c0a880a64bb 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 @@ -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())); 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 417bd37c8a9..5036c2b8829 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, "..."); } }; 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 3f87fe62b83..495e2d47697 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, @@ -173,6 +175,18 @@ impl ModuleId { self.krate } + pub fn name(self, db: &dyn db::DefDatabase) -> Option<Name> { + 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<ModuleId> { 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-expand/src/ast_id_map.rs b/src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs index 1906ed15bae..40726505491 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/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 5292a5fa1b1..204227e3387 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -12,11 +12,15 @@ use syntax::{ use triomphe::Arc; use crate::{ - ast_id_map::AstIdMap, builtin_attr_macro::pseudo_derive_attr_expansion, - builtin_fn_macro::EagerExpander, fixup, hygiene::HygieneFrame, tt, AstId, BuiltinAttrExpander, - BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, ExpandError, ExpandResult, - ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, - MacroDefKind, MacroFile, ProcMacroExpander, + ast_id_map::AstIdMap, + builtin_attr_macro::pseudo_derive_attr_expansion, + builtin_fn_macro::EagerExpander, + fixup, + hygiene::HygieneFrame, + name::{name, AsName}, + tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, + ExpandError, ExpandResult, ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, + MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander, }; /// Total limit on the number of tokens produced by any macro invocation. @@ -614,9 +618,25 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt err = error.clone().or(err); } - // Set a hard limit for the expanded tt - if let Err(value) = check_tt_count(&tt) { - return value; + // Skip checking token tree limit for include! macro call + let skip_check_tt_count = match loc.kind { + MacroCallKind::FnLike { ast_id, expand_to: _ } => { + if let Some(name_ref) = + ast_id.to_node(db).path().and_then(|p| p.segment()).and_then(|s| s.name_ref()) + { + name_ref.as_name() == name!(include) + } else { + false + } + } + _ => false, + }; + + if !skip_check_tt_count { + // Set a hard limit for the expanded tt + if let Err(value) = check_tt_count(&tt) { + return value; + } } ExpandResult { value: Arc::new(tt), err } diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml index b95ae05ccd4..c30807ad884 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml @@ -23,17 +23,17 @@ oorandom = "11.1.3" tracing = "0.1.35" rustc-hash = "1.1.0" scoped-tls = "1.0.0" -chalk-solve = { version = "0.92.0", default-features = false } -chalk-ir = "0.92.0" -chalk-recursive = { version = "0.92.0", default-features = false } -chalk-derive = "0.92.0" +chalk-solve = { version = "0.93.0", default-features = false } +chalk-ir = "0.93.0" +chalk-recursive = { version = "0.93.0", default-features = false } +chalk-derive = "0.93.0" la-arena.workspace = true once_cell = "1.17.0" triomphe.workspace = true nohash-hasher.workspace = true typed-arena = "2.0.1" -rustc_index.workspace = true +rustc-dependencies.workspace = true # local deps stdx.workspace = true @@ -56,3 +56,6 @@ project-model = { path = "../project-model" } # local deps test-utils.workspace = true + +[features] +in-rust-tree = ["rustc-dependencies/in-rust-tree"] 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 7ad3659a4f6..b395e7f4a81 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/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index 36d69edf9d5..b432588b230 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; @@ -19,7 +20,7 @@ use hir_def::{ hir::{Pat, PatId}, src::HasSource, AdtId, AttrDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ItemContainerId, - Lookup, ModuleDefId, StaticId, StructId, + 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(_)) { @@ -336,48 +389,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::<ast::IdentPat>() { 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); } } } 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 2c136896209..cbe1af15703 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<String> { 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<String>), 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<F: Fn(char) -> 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 f8cdeaa5e35..2e04bbfee83 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/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 78d3c667a1f..3d5ed1f93c0 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<PatId, Vec<Ty>>, - pub binding_modes: ArenaMap<BindingId, BindingMode>, + /// 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<PatId, BindingMode>, pub expr_adjustments: FxHashMap<ExprId, Vec<Adjustment>>, pub(crate) closure_info: FxHashMap<ClosureId, (Vec<CapturedItem>, FnTrait)>, // FIXME: remove this field 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 13d6b5643ac..0805e20447a 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)); @@ -838,8 +838,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()); 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 4e28ec06023..7ff12e5b7f8 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/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index 1a6106c0244..603e58f9d46 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -9,6 +9,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; @@ -34,7 +38,7 @@ 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,9 +48,28 @@ impl rustc_index::vec::Idx for RustcEnumVariantIdx { } } -pub type Layout = LayoutS<RustcEnumVariantIdx>; +#[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<RustcFieldIdx, RustcEnumVariantIdx>; pub type TagEncoding = hir_def::layout::TagEncoding<RustcEnumVariantIdx>; -pub type Variants = hir_def::layout::Variants<RustcEnumVariantIdx>; +pub type Variants = hir_def::layout::Variants<RustcFieldIdx, RustcEnumVariantIdx>; #[derive(Debug, PartialEq, Eq, Clone)] pub enum LayoutError { @@ -66,7 +89,7 @@ struct LayoutCx<'a> { impl<'a> LayoutCalculator for LayoutCx<'a> { type TargetDataLayoutRef = &'a TargetDataLayout; - fn delay_bug(&self, txt: &str) { + fn delay_bug(&self, txt: String) { never!("{}", txt); } @@ -145,6 +168,8 @@ fn layout_of_simd_ty( largest_niche: e_ly.largest_niche, size, align, + max_repr_align: None, + unadjusted_abi_align: align.abi, })) } @@ -230,7 +255,7 @@ pub fn layout_of_ty_query( .map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), trait_env.clone())) .collect::<Result<Vec<_>, _>>()?; let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>(); - let fields = fields.iter().collect::<Vec<_>>(); + let fields = fields.iter().collect::<IndexVec<_, _>>(); cx.univariant(dl, &fields, &ReprOptions::default(), kind).ok_or(LayoutError::Unknown)? } TyKind::Array(element, count) => { @@ -255,6 +280,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 +293,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 +333,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,22 +347,7 @@ 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 { @@ -333,7 +357,7 @@ pub fn layout_of_ty_query( 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 +387,7 @@ pub fn layout_of_ty_query( }) .collect::<Result<Vec<_>, _>>()?; let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>(); - let fields = fields.iter().collect::<Vec<_>>(); + let fields = fields.iter().collect::<IndexVec<_, _>>(); cx.univariant(dl, &fields, &ReprOptions::default(), StructKind::AlwaysSized) .ok_or(LayoutError::Unknown)? } @@ -398,9 +422,9 @@ pub fn layout_of_ty_recover( } fn layout_of_unit(cx: &LayoutCx<'_>, dl: &TargetDataLayout) -> Result<Layout, LayoutError> { - cx.univariant::<RustcEnumVariantIdx, &&Layout>( + cx.univariant::<RustcFieldIdx, RustcEnumVariantIdx, &&Layout>( 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 85ef649b895..5e713c17cf8 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::<Vec<_>>()) .collect::<SmallVec<[_; 1]>>(); - let variants = variants.iter().map(|it| it.iter().collect()).collect(); + let variants = variants.iter().map(|it| it.iter().collect()).collect::<IndexVec<_, _>>(); 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<u128>, 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); } } 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 bbe855a14de..939025461f3 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 405bb001b5d..c14339f6afe 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 { 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 e953058ccca..747ca54858c 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<ProjectionId> { + pub fn intern_if_exist(&self, projection: &[PlaceElem]) -> Option<ProjectionId> { 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,20 @@ impl ProjectionStore { } impl ProjectionId { - const EMPTY: ProjectionId = ProjectionId(0); + pub const EMPTY: ProjectionId = ProjectionId(0); - 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 +1007,7 @@ pub enum Rvalue { #[derive(Debug, PartialEq, Eq, Clone)] pub enum StatementKind { Assign(Place, Rvalue), - //FakeRead(Box<(FakeReadCause, Place)>), + FakeRead(Place), //SetDiscriminant { // place: Box<Place>, // variant_index: VariantIdx, @@ -1109,7 +1109,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 => (), 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 41fb129652a..74c5efd6c3f 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<MirSpan> }, Not, + Unused, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -144,7 +145,8 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef> } } }, - 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<LocalId, MutabilityReason>) { + 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<LocalId, MutabilityReason>) { + match &mut result[local] { + it @ MutabilityReason::Unused => { + *it = MutabilityReason::Not; + } + _ => (), + }; +} + +fn record_usage_for_operand(arg: &Operand, result: &mut ArenaMap<LocalId, MutabilityReason>) { + if let Operand::Copy(p) | Operand::Move(p) = arg { + record_usage(p.local, result); + } +} + fn mutability_of_locals( db: &dyn HirDatabase, body: &MirBody, ) -> ArenaMap<LocalId, MutabilityReason> { let mut result: ArenaMap<LocalId, MutabilityReason> = - 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 4364e0d323b..62efb858511 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<FxHashSet<FunctionId>>, mir_or_dyn_index_cache: RefCell<FxHashMap<(FunctionId, Substitution), MirOrDynIndex>>, /// 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<FxHashMap<DefWithBodyId, Vec<Locals>>>, 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<T>`, `Rc<T>`, `Arc<T>`, and `Pin<P>` where `P` is one of possible recievers, + // `&T`, `&mut T`, `Box<T>`, `Rc<T>`, `Arc<T>`, and `Pin<P>` 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 803ef631f1e..2de99e41659 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 dd2dba717f9..9905d522146 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 @@ -529,6 +529,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( @@ -668,6 +669,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) = @@ -1299,6 +1301,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 +1578,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 +1746,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,13 +1774,14 @@ 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); }; + self.push_fake_read(c, p, expr.into()); current = scope2.pop_and_drop(self, c); } } 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 270f75ad967..1120bb1c112 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<BasicBlockId>, ) -> Result<(BasicBlockId, Option<BasicBlockId>)> { 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 df16d0d8201..7d2bb95d931 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 0108859ff32..6e42bee97f7 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 @@ -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 d22d0d85c8e..1446e83fa88 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/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml index f860ee94845..09ab60dd549 100644 --- a/src/tools/rust-analyzer/crates/hir/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml @@ -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 479138b67f8..67d3169243c 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -66,6 +66,7 @@ diagnostics![ UnresolvedModule, UnresolvedProcMacro, UnusedMut, + UnusedVariable, ]; #[derive(Debug)] @@ -173,20 +174,19 @@ pub struct MalformedDerive { #[derive(Debug)] pub struct NoSuchField { - pub field: InFile<Either<AstPtr<ast::RecordExprField>, AstPtr<ast::RecordPatField>>>, + pub field: InFile<AstPtr<Either<ast::RecordExprField, ast::RecordPatField>>>, pub private: bool, } #[derive(Debug)] pub struct PrivateAssocItem { - pub expr_or_pat: - InFile<Either<AstPtr<ast::Expr>, Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>>>, + pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, Either<ast::Pat, ast::SelfParam>>>>, pub item: AssocItem, } #[derive(Debug)] pub struct MismatchedTupleStructPatArgCount { - pub expr_or_pat: InFile<Either<AstPtr<ast::Expr>, AstPtr<ast::Pat>>>, + pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>, pub expected: usize, pub found: usize, } @@ -227,7 +227,7 @@ pub struct MissingUnsafe { #[derive(Debug)] pub struct MissingFields { pub file: HirFileId, - pub field_list_parent: Either<AstPtr<ast::RecordExpr>, AstPtr<ast::RecordPat>>, + pub field_list_parent: AstPtr<Either<ast::RecordExpr, ast::RecordPat>>, pub field_list_parent_path: Option<AstPtr<ast::Path>>, pub missed_fields: Vec<Name>, } @@ -254,7 +254,7 @@ pub struct MissingMatchArms { #[derive(Debug)] pub struct TypeMismatch { - pub expr_or_pat: Either<InFile<AstPtr<ast::Expr>>, InFile<AstPtr<ast::Pat>>>, + pub expr_or_pat: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>, pub expected: Type, pub actual: Type, } @@ -271,6 +271,11 @@ pub struct UnusedMut { } #[derive(Debug)] +pub struct UnusedVariable { + pub local: Local, +} + +#[derive(Debug)] pub struct MovedOutOfRef { pub ty: Type, pub span: InFile<SyntaxNodePtr>, diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index b215ed38f28..93859611668 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 @@ //! <https://www.tedinski.com/2018/02/06/system-boundaries.html>. #![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; @@ -64,7 +65,7 @@ use hir_ty::{ 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}, primitive::UintTy, @@ -98,7 +99,7 @@ pub use crate::{ ReplaceFilterMapNextWithFindMap, TypeMismatch, TypedHole, UndeclaredLabel, UnimplementedBuiltinMacro, UnreachableLabel, UnresolvedExternCrate, UnresolvedField, UnresolvedImport, UnresolvedMacroCall, UnresolvedMethodCall, UnresolvedModule, - UnresolvedProcMacro, UnusedMut, + UnresolvedProcMacro, UnusedMut, UnusedVariable, }, has_source::HasSource, semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits}, @@ -452,15 +453,7 @@ impl HasVisibility for ModuleDef { impl Module { /// Name of this module. pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { - 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 +564,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() { @@ -1509,10 +1503,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 +1524,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 +1603,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<Pat, SelfParam> -> 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 +1627,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<Pat, SelfParam> -> 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 +1670,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 +1697,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 +1721,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 +1760,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 +1783,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::<ast::RecordPat>() + { 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(), + ) } } } @@ -1960,6 +1968,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 +2945,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 }) @@ -4515,15 +4534,31 @@ impl Layout { Some(self.0.largest_niche?.available(&*self.1)) } - pub fn field_offset(&self, idx: usize) -> Option<u64> { + pub fn field_offset(&self, field: Field) -> Option<u64> { + 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<u64> { 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 f29fb1edf00..55c2f8324c6 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<BindingMode> { - 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/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 3b162d7c4d8..c8b78b09416 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 @@ -273,9 +273,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) } @@ -446,21 +447,23 @@ fn build_pat( mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var), prefer_no_std)?); // 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 +1944,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/apply_demorgan.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs index 66bc2f6dadc..2d41243c20e 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 7acf2ea0a0d..cafd57a9772 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}; @@ -129,10 +129,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 +145,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 +287,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 +740,7 @@ fn main() { #[test] fn associated_trait_function() { - check_assist( + check_assist_by_label( auto_import, r" mod test_mod { @@ -739,6 +774,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 +849,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 +920,7 @@ fn main() { test_mod::TestStruct::TEST_CONST } ", + "Import `test_mod::TestTrait`", ); } @@ -847,7 +958,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 +1033,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 +1096,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 +1155,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 +1214,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 00000000000..082839118c5 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -0,0 +1,1672 @@ +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<ast::Type>, + initializer: Option<ast::Expr>, + definition: Definition, +} + +/// Attempts to find an appropriate node to apply the action to. +fn find_bool_node(ctx: &AssistContext<'_>) -> Option<BoolNodeData> { + 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<FileReferenceWithImport> { + 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, + ) + .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<ast::Expr> { + 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<ast::Pat> { + 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<ast::Expr> { + 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 <usize as Foo>::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 <usize as Foo>::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 1acd5ee9728..3f478ee7d39 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::<ast::Comment>()?; // 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::<Vec<String>>() + .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<Comment> { // // 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_to_guarded_return.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs index 7d0e424769e..73ba3f5c4cd 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), @@ -443,6 +427,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( convert_to_guarded_return, 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 00000000000..32db5ee8dab --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs @@ -0,0 +1,886 @@ +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::<ast::RetType>()?; + 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(<Either<ast::Impl, ast::Trait>>::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<Vec<ast::Pat>> { + 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, + ) + .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<ast::Expr>, 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/desugar_doc_comment.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs index ddc8a50ed40..c859e98524e 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::<Vec<_>>() + .join("\n"), }; let hashes = "#".repeat(required_hashes(&text)); 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 014c23197fa..e7c884dcb70 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::<ast::ExprStmt>() { + expr_stmt.syntax().clone() + } else if let Some(expr) = ctx.find_node_at_offset::<ast::Expr>() { + 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); @@ -236,6 +245,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( extract_variable, 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 5b13e01b133..f74fc5df4bd 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 00000000000..cb8ef395650 --- /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<T> core::ops::Index$0<Axis> 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<T> core::ops::IndexMut<Axis> for [T; 3] { +// fn index_mut(&mut self, index: Axis) -> &mut Self::Output { +// &self[index as usize] +// } +// } +// +// impl<T> core::ops::Index<Axis> 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::<ast::Impl>()?.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<T> core::ops::Index$0<Axis> 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<T> core::ops::IndexMut<Axis> for [T; 3] { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + &self[index as usize] + } +} + +impl<T> core::ops::Index<Axis> 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<T> core::ops::Index$0<Axis> 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<T> core::ops::IndexMut<Axis> 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<T> core::ops::Index<Axis> 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<Idx: ?Sized> {} + +impl<T> Index$0<i32> for [T; 3] {} +"#, + ); + } +} 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 ffab58509b1..f8c75bdb0de 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() @@ -1474,4 +1485,29 @@ 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 e69d1a29677..49dcde75d2b 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(_) @@ -952,4 +951,22 @@ fn f() { "#, ); } + + #[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 663df266b6f..965e4aa786e 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) + }, ); }, ); @@ -202,4 +210,64 @@ fn main() -> () { }"#, ) } + + #[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>(Gen); + +impl From<i32> for StructA<i32> { + fn from(value: i32) -> Self { + StructA(value + 1) + } +} + +fn main() -> () { + let a: StructA<i32> = 3.in$0to(); +}"#, + r#" +struct StructA<Gen>(Gen); + +impl From<i32> for StructA<i32> { + fn from(value: i32) -> Self { + StructA(value + 1) + } +} + +fn main() -> () { + let a: StructA<i32> = <StructA<i32>>::from(3); +}"#, + ) + } } 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 00000000000..b1daaea1ed1 --- /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::<ast::IfExpr>()?; + + 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<i32> { + Some(1) +} +fn main() { + if test().is_som$0e() {} +} +"#, + r#" +fn test() -> Option<i32> { + 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<i32> { + Ok(1) +} +fn main() { + if test().is_o$0k() {} +} +"#, + r#" +fn test() -> Result<i32> { + 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/unmerge_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs index dac216b69b7..52df30d9623 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<ast::Path> { 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 e9d4e270cdc..0bf1782a489 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 `<i32 as std::ops::Add>` + let path_type = path_segment.syntax().children().filter_map(ast::PathType::cast).last(); + 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() { <u32 as core::ops::Add>::$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 f235b554e61..03e6dfebebf 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<ast::Expr>, 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()), } @@ -801,6 +799,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<i32, String> { + return Ok(num) +} +"#, + r#" +fn foo(num: i32) -> i32 { + return num +} +"#, + ); + } + + #[test] fn unwrap_result_return_type_simple_with_closure() { check_assist( unwrap_result_return_type, 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 61e9bcdcc51..b68ed00f772 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<ast::Expr>, 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()), } @@ -733,6 +731,24 @@ fn foo() -> Result<i32, ${0:_}> { } #[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<i32, ${0:_}> { + return Ok(num) +} +"#, + ); + } + + #[test] fn wrap_return_type_in_result_simple_with_closure() { check_assist( wrap_return_type_in_result, 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 6f973ab53ee..e6f03214ed3 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/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index dfaa53449f4..da5822bba9c 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 @@ -245,6 +245,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( "auto_import", @@ -281,6 +305,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( "change_visibility", @@ -559,6 +611,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( "convert_tuple_struct_to_named_struct", @@ -1460,6 +1539,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<T> core::ops::Index$0<Axis> 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<T> core::ops::IndexMut<Axis> for [T; 3] { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + &self[index as usize] + } +} + +impl<T> core::ops::Index<Axis> 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( "generate_new", @@ -2480,6 +2595,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( "replace_let_with_if_let", @@ -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-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs index 39c1b7f7b3f..0961021e48e 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, @@ -377,9 +376,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 8f6a97e1e09..3d025f284bb 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs @@ -14,6 +14,7 @@ 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<CallableSnippets>, pub snippet_cap: Option<SnippetCap>, pub insert_use: InsertUseConfig, 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 c45cc8d7b37..ed74ef7b667 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -89,7 +89,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 { 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 2eaa42040a0..2fad293d16d 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; 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 8afce8db5ea..dfae715afe3 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/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs index 2464e8d5f81..284bdd8af21 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs @@ -64,6 +64,7 @@ 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, 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 4cdfd546f6a..21f693d79f1 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/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs index e80a289049f..d3dbd7cc227 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<T: PartialOrd "#, ); } + +fn check_signatures(src: &str, kind: CompletionItemKind, reduced: Expect, full: Expect) { + const FULL_SIGNATURES_CONFIG: crate::CompletionConfig = { + let mut x = TEST_CONFIG; + x.full_function_signatures = true; + x + }; + + // reduced signature + let completion = do_completion_with_config(TEST_CONFIG, src, kind); + assert!(completion[0].detail.is_some()); + reduced.assert_eq(completion[0].detail.as_ref().unwrap()); + + // full signature + let completion = do_completion_with_config(FULL_SIGNATURES_CONFIG, src, kind); + assert!(completion[0].detail.is_some()); + full.assert_eq(completion[0].detail.as_ref().unwrap()); +} + +#[test] +fn respects_full_function_signatures() { + check_signatures( + r#" +pub fn foo<'x, T>(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<T>() { + 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<T>() { + foo::<a_$0>(); +} +"#, + Some('_'), + expect![[r#" + tp T + bt u32 + kw crate:: + kw self:: + "#]], + ); +} 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 4ce80532e8e..ef72fc3861a 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 b63dde2c21e..722517a7677 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<Trait> { + self.find_trait("core:ops:Index") + } + pub fn core_option_Option(&self) -> Option<Enum> { 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 57563a17483..1cb6ff8627a 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", @@ -40,6 +50,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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"##, }, @@ -52,6 +66,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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"##, }, @@ -60,10 +78,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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,13 +85,25 @@ 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"##, }, @@ -90,10 +116,23 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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", @@ -131,6 +194,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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"##, }, @@ -156,6 +223,14 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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"##, }, @@ -164,6 +239,26 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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"##, }, @@ -189,6 +284,26 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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"##, }, @@ -197,6 +312,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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"##, }, @@ -222,16 +341,20 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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 { @@ -277,6 +400,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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", @@ -315,12 +446,20 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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", @@ -359,14 +498,30 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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"##, }, @@ -395,10 +550,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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,6 +561,26 @@ 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", @@ -417,16 +588,27 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, 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", @@ -460,6 +642,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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<Foo = Bar>`"##, + }, + 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", @@ -522,6 +716,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ 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,51 +740,65 @@ 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", description: r##"lint group for: non-camel-case-types, non-snake-case, non-upper-case-globals"##, }, @@ -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,27 +922,70 @@ 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,6 +1188,121 @@ $ cat $(find -name '*.s') "##, }, Lint { + label: "abi_riscv_interrupt", + description: r##"# `abi_riscv_interrupt` + +The tracking issue for this feature is: [#111889] + +[#111889]: https://github.com/rust-lang/rust/issues/111889 + +------------------------ +"##, + }, + Lint { + label: "abi_unadjusted", + description: r##"# `abi_unadjusted` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "abi_vectorcall", + description: r##"# `abi_vectorcall` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "abi_x86_interrupt", + description: r##"# `abi_x86_interrupt` + +The tracking issue for this feature is: [#40180] + +[#40180]: https://github.com/rust-lang/rust/issues/40180 + +------------------------ +"##, + }, + Lint { + label: "absolute_path", + description: r##"# `absolute_path` + +The tracking issue for this feature is: [#92750] + +[#92750]: https://github.com/rust-lang/rust/issues/92750 + +------------------------ +"##, + }, + Lint { + label: "addr_parse_ascii", + description: r##"# `addr_parse_ascii` + +The tracking issue for this feature is: [#101035] + +[#101035]: https://github.com/rust-lang/rust/issues/101035 + +------------------------ +"##, + }, + Lint { + label: "adt_const_params", + description: r##"# `adt_const_params` + +The tracking issue for this feature is: [#95174] + +[#95174]: https://github.com/rust-lang/rust/issues/95174 + +------------------------ +"##, + }, + Lint { + label: "alloc_error_handler", + description: r##"# `alloc_error_handler` + +The tracking issue for this feature is: [#51540] + +[#51540]: https://github.com/rust-lang/rust/issues/51540 + +------------------------ +"##, + }, + Lint { + label: "alloc_error_hook", + description: r##"# `alloc_error_hook` + +The tracking issue for this feature is: [#51245] + +[#51245]: https://github.com/rust-lang/rust/issues/51245 + +------------------------ +"##, + }, + Lint { + label: "alloc_internals", + description: r##"# `alloc_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "alloc_layout_extra", + description: r##"# `alloc_layout_extra` + +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` @@ -961,53 +1333,171 @@ compiler. "##, }, Lint { - label: "arbitrary_enum_discriminant", - description: r##"# `arbitrary_enum_discriminant` + label: "allow_internal_unsafe", + description: r##"# `allow_internal_unsafe` -The tracking issue for this feature is: [#60553] +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -[#60553]: https://github.com/rust-lang/rust/issues/60553 +------------------------ +"##, + }, + 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` -The `arbitrary_enum_discriminant` feature permits tuple-like and -struct-like enum variants with `#[repr(<int-type>)]` to have explicit discriminants. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -## Examples +------------------------ +"##, + }, + Lint { + label: "arbitrary_self_types", + description: r##"# `arbitrary_self_types` -```rust -#![feature(arbitrary_enum_discriminant)] - -#[allow(dead_code)] -#[repr(u8)] -enum Enum { - Unit = 3, - Tuple(u16) = 2, - Struct { - a: u8, - b: u16, - } = 1, -} +The tracking issue for this feature is: [#44874] -impl Enum { - fn tag(&self) -> u8 { - unsafe { *(self as *const Self as *const u8) } - } -} +[#44874]: https://github.com/rust-lang/rust/issues/44874 -assert_eq!(3, Enum::Unit.tag()); -assert_eq!(2, Enum::Tuple(5).tag()); -assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag()); -``` +------------------------ +"##, + }, + 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: [#72016] +The tracking issue for this feature is: [#93332] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#93332]: https://github.com/rust-lang/rust/issues/93332 ------------------------ @@ -1020,9 +1510,9 @@ This feature adds a `const <expr>` operand type to `asm!` and `global_asm!`. label: "asm_experimental_arch", description: r##"# `asm_experimental_arch` -The tracking issue for this feature is: [#72016] +The tracking issue for this feature is: [#93335] -[#72016]: https://github.com/rust-lang/rust/issues/72016 +[#93335]: https://github.com/rust-lang/rust/issues/93335 ------------------------ @@ -1035,6 +1525,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect - BPF - SPIR-V - AVR +- MSP430 +- M68k +- CSKY +- s390x ## Register classes @@ -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,42 +1670,167 @@ 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 <path>` operand type to `asm!` and `global_asm!`. -- `<path>` 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). -- `<path>` 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 ------------------------ +"##, + }, + Lint { + label: "associated_const_equality", + description: r##"# `associated_const_equality` -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. +The tracking issue for this feature is: [#92827] + +[#92827]: https://github.com/rust-lang/rust/issues/92827 + +------------------------ +"##, + }, + Lint { + label: "associated_type_bounds", + description: r##"# `associated_type_bounds` + +The tracking issue for this feature is: [#52662] + +[#52662]: https://github.com/rust-lang/rust/issues/52662 + +------------------------ +"##, + }, + Lint { + label: "associated_type_defaults", + description: r##"# `associated_type_defaults` + +The tracking issue for this feature is: [#29661] + +[#29661]: https://github.com/rust-lang/rust/issues/29661 + +------------------------ +"##, + }, + Lint { + label: "async_closure", + description: r##"# `async_closure` + +The tracking issue for this feature is: [#62290] + +[#62290]: https://github.com/rust-lang/rust/issues/62290 + +------------------------ +"##, + }, + Lint { + label: "async_fn_in_trait", + description: r##"# `async_fn_in_trait` + +The tracking issue for this feature is: [#91611] + +[#91611]: https://github.com/rust-lang/rust/issues/91611 + +------------------------ +"##, + }, + Lint { + label: "async_fn_track_caller", + description: r##"# `async_fn_track_caller` + +The tracking issue for this feature is: [#110011] + +[#110011]: https://github.com/rust-lang/rust/issues/110011 + +------------------------ +"##, + }, + Lint { + label: "async_iter_from_iter", + description: r##"# `async_iter_from_iter` + +The tracking issue for this feature is: [#81798] + +[#81798]: https://github.com/rust-lang/rust/issues/81798 + +------------------------ +"##, + }, + 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 { @@ -1184,8 +1850,8 @@ that are automatically implemented for every type, unless the type, or a type it has explicitly opted out via a negative impl. (Negative impls are separately controlled by the `negative_impls` feature.) -[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html -[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html +[`Send`]: ../../std/marker/trait.Send.html +[`Sync`]: ../../std/marker/trait.Sync.html ```rust,ignore (partial-example) impl !Trait for Type {} @@ -1278,6 +1944,116 @@ Auto traits cannot have supertraits. This is for soundness reasons, as the inter "##, }, 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 { label: "box_patterns", description: r##"# `box_patterns` @@ -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<T>`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] -[#49733]: https://github.com/rust-lang/rust/issues/49733 +[#44839]: https://github.com/rust-lang/rust/issues/44839 -See also [`box_patterns`](box-patterns.md) +------------------------ +"##, + }, + Lint { + label: "btree_cursors", + description: r##"# `btree_cursors` + +The tracking issue for this feature is: [#107540] + +[#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,45 +2284,91 @@ 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. +The tracking issue for this feature is: [#69099] -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. +[#69099]: https://github.com/rust-lang/rust/issues/69099 -## Examples +------------------------ +"##, + }, + Lint { + label: "cell_update", + description: r##"# `cell_update` -```rust -#![feature(cfg_panic)] +The tracking issue for this feature is: [#50186] -#[cfg(panic = "unwind")] -fn a() { - // ... -} +[#50186]: https://github.com/rust-lang/rust/issues/50186 -#[cfg(not(panic = "unwind"))] -fn a() { - // ... -} +------------------------ +"##, + }, + Lint { + label: "cfg_accessible", + description: r##"# `cfg_accessible` -fn b() { - if cfg!(panic = "abort") { - // ... - } else { - // ... - } -} -``` +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 { @@ -1506,6 +2410,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 { label: "cfg_version", description: r##"# `cfg_version` @@ -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 ------------------------ "##, @@ -1570,6 +2591,17 @@ available through `std::panic::Location::caller()`, just like using "##, }, 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 { label: "cmse_nonsecure_entry", description: r##"# `cmse_nonsecure_entry` @@ -1655,6 +2687,28 @@ $ arm-none-eabi-objdump -D function.o "##, }, 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 { label: "compiler_builtins", description: r##"# `compiler_builtins` @@ -1664,6 +2718,17 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, 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 + +------------------------ +"##, + }, + Lint { label: "concat_idents", description: r##"# `concat_idents` @@ -1690,14 +2755,1027 @@ 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: [#46571] + +[#46571]: https://github.com/rust-lang/rust/issues/46571 + +------------------------ +"##, + }, + Lint { + label: "const_align_of_val_raw", + description: r##"# `const_align_of_val_raw` + +The tracking issue for this feature is: [#46571] + +[#46571]: https://github.com/rust-lang/rust/issues/46571 + +------------------------ +"##, + }, + Lint { + label: "const_align_offset", + description: r##"# `const_align_offset` + +The tracking issue for this feature is: [#90962] + +[#90962]: https://github.com/rust-lang/rust/issues/90962 + +------------------------ +"##, + }, + Lint { + label: "const_alloc_error", + description: r##"# `const_alloc_error` + +The tracking issue for this feature is: [#92523] + +[#92523]: https://github.com/rust-lang/rust/issues/92523 + +------------------------ +"##, + }, + Lint { + label: "const_alloc_layout", + description: r##"# `const_alloc_layout` + +The tracking issue for this feature is: [#67521] + +[#67521]: https://github.com/rust-lang/rust/issues/67521 + +------------------------ +"##, + }, + Lint { + label: "const_arguments_as_str", + description: r##"# `const_arguments_as_str` + +The tracking issue for this feature is: [#103900] + +[#103900]: https://github.com/rust-lang/rust/issues/103900 + +------------------------ +"##, + }, + Lint { + label: "const_array_from_ref", + description: r##"# `const_array_from_ref` + +The tracking issue for this feature is: [#90206] + +[#90206]: https://github.com/rust-lang/rust/issues/90206 + +------------------------ +"##, + }, + Lint { + label: "const_array_into_iter_constructors", + description: r##"# `const_array_into_iter_constructors` + +The tracking issue for this feature is: [#91583] + +[#91583]: https://github.com/rust-lang/rust/issues/91583 + +------------------------ +"##, + }, + Lint { + label: "const_assert_type2", + description: r##"# `const_assert_type2` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_assume", + description: r##"# `const_assume` + +The tracking issue for this feature is: [#76972] + +[#76972]: https://github.com/rust-lang/rust/issues/76972 + +------------------------ +"##, + }, + Lint { + label: "const_async_blocks", + description: r##"# `const_async_blocks` + +The tracking issue for this feature is: [#85368] + +[#85368]: https://github.com/rust-lang/rust/issues/85368 + +------------------------ +"##, + }, + Lint { + label: "const_bigint_helper_methods", + description: r##"# `const_bigint_helper_methods` + +The tracking issue for this feature is: [#85532] + +[#85532]: https://github.com/rust-lang/rust/issues/85532 + +------------------------ +"##, + }, + Lint { + label: "const_black_box", + description: r##"# `const_black_box` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_box", + description: r##"# `const_box` + +The tracking issue for this feature is: [#92521] + +[#92521]: https://github.com/rust-lang/rust/issues/92521 + +------------------------ +"##, + }, + Lint { + label: "const_btree_len", + description: r##"# `const_btree_len` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_caller_location", + description: r##"# `const_caller_location` + +The tracking issue for this feature is: [#76156] + +[#76156]: https://github.com/rust-lang/rust/issues/76156 + +------------------------ +"##, + }, + Lint { + label: "const_cell_into_inner", + description: r##"# `const_cell_into_inner` + +The tracking issue for this feature is: [#78729] + +[#78729]: https://github.com/rust-lang/rust/issues/78729 + +------------------------ +"##, + }, + Lint { + label: "const_char_from_u32_unchecked", + description: r##"# `const_char_from_u32_unchecked` + +The tracking issue for this feature is: [#89259] + +[#89259]: https://github.com/rust-lang/rust/issues/89259 + +------------------------ +"##, + }, + Lint { + label: "const_closures", + description: r##"# `const_closures` + +The tracking issue for this feature is: [#106003] + +[#106003]: https://github.com/rust-lang/rust/issues/106003 + +------------------------ +"##, + }, + Lint { + label: "const_collections_with_hasher", + description: r##"# `const_collections_with_hasher` + +The tracking issue for this feature is: [#102575] + +[#102575]: https://github.com/rust-lang/rust/issues/102575 + +------------------------ +"##, + }, + Lint { + label: "const_cow_is_borrowed", + description: r##"# `const_cow_is_borrowed` + +The tracking issue for this feature is: [#65143] + +[#65143]: https://github.com/rust-lang/rust/issues/65143 + +------------------------ +"##, + }, + Lint { + label: "const_cstr_from_ptr", + description: r##"# `const_cstr_from_ptr` + +The tracking issue for this feature is: [#113219] + +[#113219]: https://github.com/rust-lang/rust/issues/113219 + +------------------------ +"##, + }, + Lint { + label: "const_discriminant", + description: r##"# `const_discriminant` + +The tracking issue for this feature is: [#69821] + +[#69821]: https://github.com/rust-lang/rust/issues/69821 + +------------------------ +"##, + }, + Lint { + label: "const_eval_select", + description: r##"# `const_eval_select` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_exact_div", + description: r##"# `const_exact_div` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_extern_fn", + description: r##"# `const_extern_fn` + +The tracking issue for this feature is: [#64926] + +[#64926]: https://github.com/rust-lang/rust/issues/64926 + +------------------------ +"##, + }, + Lint { + label: "const_float_bits_conv", + description: r##"# `const_float_bits_conv` + +The tracking issue for this feature is: [#72447] + +[#72447]: https://github.com/rust-lang/rust/issues/72447 + +------------------------ +"##, + }, + Lint { + label: "const_float_classify", + description: r##"# `const_float_classify` + +The tracking issue for this feature is: [#72505] + +[#72505]: https://github.com/rust-lang/rust/issues/72505 + +------------------------ +"##, + }, + Lint { + label: "const_fmt_arguments_new", + description: r##"# `const_fmt_arguments_new` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_fn_floating_point_arithmetic", + description: r##"# `const_fn_floating_point_arithmetic` + +The tracking issue for this feature is: [#57241] + +[#57241]: https://github.com/rust-lang/rust/issues/57241 + +------------------------ +"##, + }, + Lint { + label: "const_for", + description: r##"# `const_for` + +The tracking issue for this feature is: [#87575] + +[#87575]: https://github.com/rust-lang/rust/issues/87575 + +------------------------ +"##, + }, + Lint { + label: "const_format_args", + description: r##"# `const_format_args` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_hash", + description: r##"# `const_hash` + +The tracking issue for this feature is: [#104061] + +[#104061]: https://github.com/rust-lang/rust/issues/104061 + +------------------------ +"##, + }, + Lint { + label: "const_heap", + description: r##"# `const_heap` + +The tracking issue for this feature is: [#79597] + +[#79597]: https://github.com/rust-lang/rust/issues/79597 + +------------------------ +"##, + }, + Lint { + label: "const_index_range_slice_index", + description: r##"# `const_index_range_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_inherent_unchecked_arith", + description: r##"# `const_inherent_unchecked_arith` + +The tracking issue for this feature is: [#85122] + +[#85122]: https://github.com/rust-lang/rust/issues/85122 + +------------------------ +"##, + }, + Lint { + label: "const_int_unchecked_arith", + description: r##"# `const_int_unchecked_arith` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_intoiterator_identity", + description: r##"# `const_intoiterator_identity` + +The tracking issue for this feature is: [#90603] + +[#90603]: https://github.com/rust-lang/rust/issues/90603 + +------------------------ +"##, + }, + Lint { + label: "const_intrinsic_compare_bytes", + description: r##"# `const_intrinsic_compare_bytes` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_intrinsic_forget", + description: r##"# `const_intrinsic_forget` + +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` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_io_structs", + description: r##"# `const_io_structs` + +The tracking issue for this feature is: [#78812] + +[#78812]: https://github.com/rust-lang/rust/issues/78812 + +------------------------ +"##, + }, + Lint { + label: "const_ip", + description: r##"# `const_ip` + +The tracking issue for this feature is: [#76205] + +[#76205]: https://github.com/rust-lang/rust/issues/76205 + +------------------------ +"##, + }, + Lint { + label: "const_ipv4", + description: r##"# `const_ipv4` + +The tracking issue for this feature is: [#76205] + +[#76205]: https://github.com/rust-lang/rust/issues/76205 + +------------------------ +"##, + }, + Lint { + label: "const_ipv6", + description: r##"# `const_ipv6` + +The tracking issue for this feature is: [#76205] + +[#76205]: https://github.com/rust-lang/rust/issues/76205 + +------------------------ +"##, + }, + Lint { + label: "const_likely", + description: r##"# `const_likely` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_location_fields", + description: r##"# `const_location_fields` + +The tracking issue for this feature is: [#102911] + +[#102911]: https://github.com/rust-lang/rust/issues/102911 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_array_assume_init", + description: r##"# `const_maybe_uninit_array_assume_init` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_as_mut_ptr", + description: r##"# `const_maybe_uninit_as_mut_ptr` + +The tracking issue for this feature is: [#75251] + +[#75251]: https://github.com/rust-lang/rust/issues/75251 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_assume_init", + description: r##"# `const_maybe_uninit_assume_init` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_assume_init_read", + description: r##"# `const_maybe_uninit_assume_init_read` + +The tracking issue for this feature is: [#63567] + +[#63567]: https://github.com/rust-lang/rust/issues/63567 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_uninit_array", + description: r##"# `const_maybe_uninit_uninit_array` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_write", + description: r##"# `const_maybe_uninit_write` + +The tracking issue for this feature is: [#63567] + +[#63567]: https://github.com/rust-lang/rust/issues/63567 + +------------------------ +"##, + }, + Lint { + label: "const_maybe_uninit_zeroed", + description: r##"# `const_maybe_uninit_zeroed` + +The tracking issue for this feature is: [#91850] + +[#91850]: https://github.com/rust-lang/rust/issues/91850 + +------------------------ +"##, + }, + Lint { + label: "const_mut_refs", + description: r##"# `const_mut_refs` -The tracking issue for this feature is: [#67217] +The tracking issue for this feature is: [#57349] -[#67217]: https://github.com/rust-lang/rust/issues/67217 +[#57349]: https://github.com/rust-lang/rust/issues/57349 -The `const_eval_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`. +------------------------ +"##, + }, + Lint { + label: "const_nonnull_new", + description: r##"# `const_nonnull_new` + +The tracking issue for this feature is: [#93235] + +[#93235]: https://github.com/rust-lang/rust/issues/93235 + +------------------------ +"##, + }, + Lint { + label: "const_num_midpoint", + description: r##"# `const_num_midpoint` + +The tracking issue for this feature is: [#110840] + +[#110840]: https://github.com/rust-lang/rust/issues/110840 + +------------------------ +"##, + }, + Lint { + label: "const_option", + description: r##"# `const_option` + +The tracking issue for this feature is: [#67441] + +[#67441]: https://github.com/rust-lang/rust/issues/67441 + +------------------------ +"##, + }, + Lint { + label: "const_option_ext", + description: r##"# `const_option_ext` + +The tracking issue for this feature is: [#91930] + +[#91930]: https://github.com/rust-lang/rust/issues/91930 + +------------------------ +"##, + }, + Lint { + label: "const_pin", + description: r##"# `const_pin` + +The tracking issue for this feature is: [#76654] + +[#76654]: https://github.com/rust-lang/rust/issues/76654 + +------------------------ +"##, + }, + Lint { + label: "const_pointer_byte_offsets", + description: r##"# `const_pointer_byte_offsets` + +The tracking issue for this feature is: [#96283] + +[#96283]: https://github.com/rust-lang/rust/issues/96283 + +------------------------ +"##, + }, + Lint { + label: "const_pointer_is_aligned", + description: r##"# `const_pointer_is_aligned` + +The tracking issue for this feature is: [#104203] + +[#104203]: https://github.com/rust-lang/rust/issues/104203 + +------------------------ +"##, + }, + Lint { + label: "const_precise_live_drops", + description: r##"# `const_precise_live_drops` + +The tracking issue for this feature is: [#73255] + +[#73255]: https://github.com/rust-lang/rust/issues/73255 + +------------------------ +"##, + }, + Lint { + label: "const_pref_align_of", + description: r##"# `const_pref_align_of` + +The tracking issue for this feature is: [#91971] + +[#91971]: https://github.com/rust-lang/rust/issues/91971 + +------------------------ +"##, + }, + Lint { + label: "const_ptr_as_ref", + description: r##"# `const_ptr_as_ref` + +The tracking issue for this feature is: [#91822] + +[#91822]: https://github.com/rust-lang/rust/issues/91822 + +------------------------ +"##, + }, + Lint { + label: "const_ptr_is_null", + description: r##"# `const_ptr_is_null` + +The tracking issue for this feature is: [#74939] + +[#74939]: https://github.com/rust-lang/rust/issues/74939 + +------------------------ +"##, + }, + Lint { + label: "const_ptr_sub_ptr", + description: r##"# `const_ptr_sub_ptr` + +The tracking issue for this feature is: [#95892] + +[#95892]: https://github.com/rust-lang/rust/issues/95892 + +------------------------ +"##, + }, + Lint { + label: "const_ptr_write", + description: r##"# `const_ptr_write` + +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 { @@ -1737,30 +3815,115 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { - label: "crate_visibility_modifier", - description: r##"# `crate_visibility_modifier` + label: "coverage_attribute", + description: r##"# `coverage_attribute` -The tracking issue for this feature is: [#53120] +The tracking issue for this feature is: [#84605] -[#53120]: https://github.com/rust-lang/rust/issues/53120 +[#84605]: https://github.com/rust-lang/rust/issues/84605 ------ +--- -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 `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(crate_visibility_modifier)] +#![feature(coverage_attribute)] -crate struct Foo { - bar: usize, +// `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` @@ -1797,6 +3960,17 @@ 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` @@ -1806,54 +3980,47 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { - label: "default_free_fn", - description: r##"# `default_free_fn` + label: "decl_macro", + description: r##"# `decl_macro` -The tracking issue for this feature is: [#73014] +The tracking issue for this feature is: [#39412] -[#73014]: https://github.com/rust-lang/rust/issues/73014 +[#39412]: https://github.com/rust-lang/rust/issues/39412 ------------------------ +"##, + }, + Lint { + label: "default_type_parameter_fallback", + description: r##"# `default_type_parameter_fallback` -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. +The tracking issue for this feature is: [#27336] -[`Default::default()`]: https://doc.rust-lang.org/nightly/std/default/trait.Default.html#tymethod.default +[#27336]: https://github.com/rust-lang/rust/issues/27336 -Here is an example: +------------------------ +"##, + }, + Lint { + label: "deprecated_safe", + description: r##"# `deprecated_safe` -```rust -#![feature(default_free_fn)] -use std::default::default; +The tracking issue for this feature is: [#94978] -#[derive(Default)] -struct AppConfig { - foo: FooConfig, - bar: BarConfig, -} +[#94978]: https://github.com/rust-lang/rust/issues/94978 -#[derive(Default)] -struct FooConfig { - foo: i32, -} +------------------------ +"##, + }, + Lint { + label: "deprecated_suggestion", + description: r##"# `deprecated_suggestion` -#[derive(Default)] -struct BarConfig { - bar: f32, - baz: u8, -} +The tracking issue for this feature is: [#94785] -fn main() { - let options = AppConfig { - foo: default(), - bar: BarConfig { - bar: 10.1, - ..default() - }, - }; -} -``` +[#94785]: https://github.com/rust-lang/rust/issues/94785 + +------------------------ "##, }, Lint { @@ -1866,6 +4033,15 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, 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` @@ -1875,6 +4051,79 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, 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` @@ -1885,7 +4134,7 @@ 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 "This is supported on +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. @@ -1925,6 +4174,17 @@ pub struct Icon { "##, }, 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` @@ -1990,6 +4250,180 @@ See also its documentation in [the rustdoc book][rustdoc-book-notable_trait]. "##, }, 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` @@ -2020,60 +4454,105 @@ stabilized. "##, }, Lint { - label: "explicit_generic_args_with_impl_trait", - description: r##"# `explicit_generic_args_with_impl_trait` + label: "exclusive_wrapper", + description: r##"# `exclusive_wrapper` -The tracking issue for this feature is: [#83701] +The tracking issue for this feature is: [#98407] -[#83701]: https://github.com/rust-lang/rust/issues/83701 +[#98407]: https://github.com/rust-lang/rust/issues/98407 ------------------------ +"##, + }, + Lint { + label: "exhaustive_patterns", + description: r##"# `exhaustive_patterns` -The `explicit_generic_args_with_impl_trait` feature gate lets you specify generic arguments even -when `impl Trait` is used in argument position. +The tracking issue for this feature is: [#51085] -A simple example is: +[#51085]: https://github.com/rust-lang/rust/issues/51085 -```rust -#![feature(explicit_generic_args_with_impl_trait)] +------------------------ +"##, + }, + Lint { + label: "exit_status_error", + description: r##"# `exit_status_error` -fn foo<T: ?Sized>(_f: impl AsRef<T>) {} +The tracking issue for this feature is: [#84908] -fn main() { - foo::<str>("".to_string()); -} -``` +[#84908]: https://github.com/rust-lang/rust/issues/84908 -This is currently rejected: +------------------------ +"##, + }, + Lint { + label: "exitcode_exit_method", + description: r##"# `exitcode_exit_method` -```text -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> src/main.rs:6:11 - | -6 | foo::<str>("".to_string()); - | ^^^ explicit generic argument not allowed +The tracking issue for this feature is: [#97100] -``` +[#97100]: https://github.com/rust-lang/rust/issues/97100 -However it would compile if `explicit_generic_args_with_impl_trait` is enabled. +------------------------ +"##, + }, + Lint { + label: "explicit_tail_calls", + description: r##"# `explicit_tail_calls` -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: [#112788] -```rust,compile_fail -#![feature(explicit_generic_args_with_impl_trait)] +[#112788]: https://github.com/rust-lang/rust/issues/112788 -fn foo<T: ?Sized>(_f: impl AsRef<T>) {} -fn bar<T: ?Sized, F: AsRef<T>>(_f: F) {} +------------------------ +"##, + }, + Lint { + label: "extend_one", + description: r##"# `extend_one` -fn main() { - bar::<str, _>("".to_string()); // Okay - bar::<str, String>("".to_string()); // Okay +The tracking issue for this feature is: [#72631] - foo::<str>("".to_string()); // Okay - foo::<str, String>("".to_string()); // Error, you cannot specify `impl Trait` explicitly -} -``` +[#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 { @@ -2211,6 +4690,72 @@ against are compatible with those of the `#[ffi_pure]`. "##, }, 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` @@ -2220,6 +4765,15 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, 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` @@ -2229,6 +4783,26 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, 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` @@ -2243,7 +4817,7 @@ See Also: [`unboxed_closures`](../language-features/unboxed-closures.md) The `fn_traits` feature allows for implementation of the [`Fn*`] traits for creating custom closure-like types. -[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html +[`Fn*`]: ../../std/ops/trait.Fn.html ```rust #![feature(unboxed_closures)] @@ -2268,6 +4842,90 @@ fn main() { "##, }, 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` @@ -2518,82 +5176,253 @@ does. "##, }, Lint { - label: "half_open_range_patterns", - description: r##"# `half_open_range_patterns` + 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, +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 ----- -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. - -It also enabled RangeFrom patterns but that has since been -stabilized. +This feature allow using top-level half-open range patterns in slices. ```rust -#![feature(half_open_range_patterns)] +#![feature(half_open_range_patterns_in_slices)] #![feature(exclusive_range_pattern)] - let x = 5; - match x { - ..0 => println!("negative!"), // "RangeTo" pattern. Unstable. - 0 => println!("zero!"), - 1.. => println!("positive!"), // "RangeFrom" pattern. Stable. - } + +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: "infer_static_outlives_requirements", - description: r##"# `infer_static_outlives_requirements` + label: "hash_extract_if", + description: r##"# `hash_extract_if` -The tracking issue for this feature is: [#54185] +The tracking issue for this feature is: [#59618] -[#54185]: https://github.com/rust-lang/rust/issues/54185 +[#59618]: https://github.com/rust-lang/rust/issues/59618 ------------------------ -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: "hash_raw_entry", + description: r##"# `hash_raw_entry` -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: [#56167] -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. +[#56167]: https://github.com/rust-lang/rust/issues/56167 -```rust,ignore (pseudo-Rust) -struct Foo<U> where U: 'static { // <-- currently required - bar: Bar<U> -} -struct Bar<T: 'static> { - x: T, -} -``` +------------------------ +"##, + }, + Lint { + label: "hash_set_entry", + description: r##"# `hash_set_entry` +The tracking issue for this feature is: [#60896] -## Examples: +[#60896]: https://github.com/rust-lang/rust/issues/60896 -```rust,ignore (pseudo-Rust) -#![feature(infer_outlives_requirements)] -#![feature(infer_static_outlives_requirements)] +------------------------ +"##, + }, + Lint { + label: "hasher_prefixfree_extras", + description: r##"# `hasher_prefixfree_extras` -#[rustc_outlives] -// Implicitly infer U: 'static -struct Foo<U> { - bar: Bar<U> -} -struct Bar<T: 'static> { - x: T, -} -``` +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 { @@ -2661,10 +5490,41 @@ match some_int { "##, }, Lint { - label: "int_error_internals", - description: r##"# `int_error_internals` + label: "inplace_iteration", + description: r##"# `inplace_iteration` -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: "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. ------------------------ "##, @@ -2718,12 +5578,13 @@ via a declaration like ```rust #![feature(intrinsics)] +#![allow(internal_features)] # fn main() {} extern "rust-intrinsic" { fn transmute<T, U>(x: T) -> U; - fn offset<T>(dst: *const T, offset: isize) -> *const T; + fn arith_offset<T>(dst: *const T, offset: isize) -> *const T; } ``` @@ -2731,6 +5592,92 @@ 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` @@ -2746,6 +5693,160 @@ add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to "##, }, 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` @@ -2758,304 +5859,190 @@ 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'. +items'. Most of them can only be defined once. -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`: +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, box_syntax, start, libc, core_intrinsics, rustc_private)] +#![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; -extern crate libc; +pub struct Global; // the global allocator +struct Unique<T>(NonNull<T>); #[lang = "owned_box"] -pub struct Box<T>(*mut T); +pub struct Box<T, A = Global>(Unique<T>, A); + +impl<T> Box<T> { + pub fn new(x: T) -> Self { + #[rustc_box] + Box::new(x) + } +} + +impl<T, A> Drop for Box<T, A> { + 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 libc::size_t) as *mut u8; + let p = libc::malloc(size) as *mut u8; // Check if `malloc` failed: - if p as usize == 0 { + if p.is_null() { intrinsics::abort(); } p } -#[lang = "box_free"] -unsafe fn box_free<T: ?Sized>(ptr: *mut T) { - libc::free(ptr as *mut libc::c_void) -} - #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { - let _x = box 1; + let _x = Box::new(1); 0 } -#[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 () {} +#[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. -Other features provided by lang items include: - -- 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 } -``` - -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.** - -### Writing an executable without stdlib - -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. - -The function marked `#[start]` is passed the command line parameters -in the same format as C: +## List of all language items -```rust,ignore (libc-is-finicky) -#![feature(lang_items, core_intrinsics, rustc_private)] -#![feature(start)] -#![no_std] -use core::intrinsics; -use core::panic::PanicInfo; +An up-to-date list of all language items can be found [here] in the compiler code. -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; +[here]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs +"##, + }, + Lint { + label: "large_assignments", + description: r##"# `large_assignments` -// Entry point for this program. -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} +The tracking issue for this feature is: [#83518] -// 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() { -} +[#83518]: https://github.com/rust-lang/rust/issues/83518 -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` +------------------------ +"##, + }, + Lint { + label: "layout_for_ptr", + description: r##"# `layout_for_ptr` -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: +The tracking issue for this feature is: [#69835] -```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; +[#69835]: https://github.com/rust-lang/rust/issues/69835 -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; +------------------------ +"##, + }, + Lint { + label: "lazy_cell", + description: r##"# `lazy_cell` -// 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: [#109736] -// 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() { -} +[#109736]: https://github.com/rust-lang/rust/issues/109736 -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` +------------------------ +"##, + }, + Lint { + label: "lazy_cell_consume", + description: r##"# `lazy_cell_consume` -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: [#109736] -## More about the language items +[#109736]: https://github.com/rust-lang/rust/issues/109736 -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. +------------------------ +"##, + }, + Lint { + label: "lazy_type_alias", + description: r##"# `lazy_type_alias` -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 tracking issue for this feature is: [#112792] -[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs +[#112792]: https://github.com/rust-lang/rust/issues/112792 -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`. +------------------------ +"##, + }, + Lint { + label: "let_chains", + description: r##"# `let_chains` -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: [#53667] -## List of all language items +[#53667]: https://github.com/rust-lang/rust/issues/53667 -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: "liballoc_internals", + description: r##"# `liballoc_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: "libstd_thread_internals", - description: r##"# `libstd_thread_internals` + label: "libstd_sys_internals", + description: r##"# `libstd_sys_internals` This feature is internal to the Rust compiler and is not intended for general use. @@ -3072,197 +6059,124 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { - label: "llvm_asm", - description: r##"# `llvm_asm` + label: "link_llvm_intrinsics", + description: r##"# `link_llvm_intrinsics` -The tracking issue for this feature is: [#70173] +The tracking issue for this feature is: [#29602] -[#70173]: https://github.com/rust-lang/rust/issues/70173 +[#29602]: https://github.com/rust-lang/rust/issues/29602 ------------------------ +"##, + }, + Lint { + label: "linkage", + description: r##"# `linkage` -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. - -```rust,ignore (pseudo-code) -llvm_asm!(assembly template - : output operands - : input operands - : clobbers - : options - ); -``` - -Any use of `llvm_asm` is feature gated (requires `#![feature(llvm_asm)]` on the -crate to allow) and of course requires an `unsafe` block. - -> **Note**: the examples here are given in x86/x86-64 assembly, but -> all platforms are supported. - -## Assembly template +The tracking issue for this feature is: [#29603] -The `assembly template` is the only required parameter and must be a -literal string (i.e. `""`) +[#29603]: https://github.com/rust-lang/rust/issues/29603 -```rust -#![feature(llvm_asm)] +------------------------ +"##, + }, + Lint { + label: "linked_list_cursors", + description: r##"# `linked_list_cursors` -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn foo() { - unsafe { - llvm_asm!("NOP"); - } -} +The tracking issue for this feature is: [#58533] -// Other platforms: -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -fn foo() { /* ... */ } +[#58533]: https://github.com/rust-lang/rust/issues/58533 -fn main() { - // ... - foo(); - // ... -} -``` +------------------------ +"##, + }, + Lint { + label: "linked_list_remove", + description: r##"# `linked_list_remove` -(The `feature(llvm_asm)` and `#[cfg]`s are omitted from now on.) +The tracking issue for this feature is: [#69210] -Output operands, input operands, clobbers and options are all optional -but you must add the right number of `:` if you skip them: +[#69210]: https://github.com/rust-lang/rust/issues/69210 -```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() {} -``` +------------------------ +"##, + }, + Lint { + label: "lint_reasons", + description: r##"# `lint_reasons` -Whitespace also doesn't matter: +The tracking issue for this feature is: [#54503] -```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() {} -``` +[#54503]: https://github.com/rust-lang/rust/issues/54503 -## Operands +------------------------ +"##, + }, + Lint { + label: "linux_pidfd", + description: r##"# `linux_pidfd` -Input and output operands follow the same format: `: -"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand -expressions must be mutable place, or not yet assigned: +The tracking issue for this feature is: [#82971] -```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 } +[#82971]: https://github.com/rust-lang/rust/issues/82971 -fn main() { - assert_eq!(add(3, 14159), 14162) -} -``` +------------------------ +"##, + }, + Lint { + label: "log_syntax", + description: r##"# `log_syntax` -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: +The tracking issue for this feature is: [#29598] -```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 -# } -``` +[#29598]: https://github.com/rust-lang/rust/issues/29598 -## Clobbers +------------------------ +"##, + }, + Lint { + label: "macro_metavar_expr", + description: r##"# `macro_metavar_expr` -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. +The tracking issue for this feature is: [#83527] -```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() {} -``` +[#83527]: https://github.com/rust-lang/rust/issues/83527 -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. +------------------------ +"##, + }, + Lint { + label: "map_entry_replace", + description: r##"# `map_entry_replace` -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. +The tracking issue for this feature is: [#44286] -## Options +[#44286]: https://github.com/rust-lang/rust/issues/44286 -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: +------------------------ +"##, + }, + Lint { + label: "map_many_mut", + description: r##"# `map_many_mut` -Current valid options are: +The tracking issue for this feature is: [#97601] -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. +[#97601]: https://github.com/rust-lang/rust/issues/97601 -```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") -} -println!("eax is currently {}", result); -# } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` +------------------------ +"##, + }, + Lint { + label: "map_try_insert", + description: r##"# `map_try_insert` -## More Information +The tracking issue for this feature is: [#82766] -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. +[#82766]: https://github.com/rust-lang/rust/issues/82766 -[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions +------------------------ "##, }, Lint { @@ -3305,6 +6219,116 @@ 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` @@ -3338,68 +6362,61 @@ impl A for Foo { "##, }, Lint { - label: "native_link_modifiers", - description: r##"# `native_link_modifiers` + label: "multiple_supertrait_upcastable", + description: r##"# `multiple_supertrait_upcastable` -The tracking issue for this feature is: [#81490] - -[#81490]: https://github.com/rust-lang/rust/issues/81490 +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ - -The `native_link_modifiers` feature allows you to use the `modifiers` syntax with the `#[link(..)]` attribute. - -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: "must_not_suspend", + description: r##"# `must_not_suspend` -The tracking issue for this feature is: [#81490] +The tracking issue for this feature is: [#83310] -[#81490]: https://github.com/rust-lang/rust/issues/81490 +[#83310]: https://github.com/rust-lang/rust/issues/83310 ------------------------ - -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: "native_link_modifiers_bundle", - description: r##"# `native_link_modifiers_bundle` + label: "mutex_unlock", + description: r##"# `mutex_unlock` -The tracking issue for this feature is: [#81490] +The tracking issue for this feature is: [#81872] -[#81490]: https://github.com/rust-lang/rust/issues/81490 +[#81872]: https://github.com/rust-lang/rust/issues/81872 ------------------------ +"##, + }, + Lint { + label: "mutex_unpoison", + description: r##"# `mutex_unpoison` -The `native_link_modifiers_bundle` feature allows you to use the `bundle` modifier. +The tracking issue for this feature is: [#96469] -Only compatible with the `static` linking kind. Using any other kind will result in a compiler error. +[#96469]: https://github.com/rust-lang/rust/issues/96469 -`+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: "naked_functions", + description: r##"# `naked_functions` -`-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: [#32408] -This modifier is supposed to supersede the `static-nobundle` linking kind defined by [RFC 1717](https://github.com/rust-lang/rfcs/pull/1717). +[#32408]: https://github.com/rust-lang/rust/issues/32408 -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: "native_link_modifiers_as_needed", + description: r##"# `native_link_modifiers_as_needed` The tracking issue for this feature is: [#81490] @@ -3407,40 +6424,36 @@ The tracking issue for this feature is: [#81490] ------------------------ -The `native_link_modifiers_verbatim` feature allows you to use the `verbatim` modifier. +The `native_link_modifiers_as_needed` feature allows you to use the `as-needed` 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. +`as-needed` is only compatible with the `dynamic` and `framework` linking kinds. Using any other kind will result in a compiler error. -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. +`+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. -The default for this modifier is `-verbatim`. +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`). -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`. +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: "native_link_modifiers_whole_archive", - description: r##"# `native_link_modifiers_whole_archive` + label: "needs_panic_runtime", + description: r##"# `needs_panic_runtime` -The tracking issue for this feature is: [#81490] +The tracking issue for this feature is: [#32837] -[#81490]: https://github.com/rust-lang/rust/issues/81490 +[#32837]: https://github.com/rust-lang/rust/issues/32837 ------------------------ +"##, + }, + Lint { + label: "negative_bounds", + description: r##"# `negative_bounds` -The `native_link_modifiers_whole_archive` feature allows you to use the `whole-archive` modifier. - -Only compatible with the `static` linking kind. Using any other kind will result in a compiler error. - -`+whole-archive` means that the static library is linked as a whole archive without throwing any object files away. - -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. +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -The default for this modifier is `-whole-archive`. +------------------------ "##, }, Lint { @@ -3505,37 +6518,47 @@ This serves two purposes: "##, }, Lint { - label: "coverage", - description: r##"# `coverage` + label: "never_type", + description: r##"# `never_type` -The tracking issue for this feature is: [#84605] +The tracking issue for this feature is: [#35121] -[#84605]: https://github.com/rust-lang/rust/issues/84605 +[#35121]: https://github.com/rust-lang/rust/issues/35121 ---- +------------------------ +"##, + }, + Lint { + label: "never_type_fallback", + description: r##"# `never_type_fallback` -The `coverage` attribute can be used to selectively disable coverage -instrumentation in an annotated function. This might be useful to: +The tracking issue for this feature is: [#65992] -- 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. +[#65992]: https://github.com/rust-lang/rust/issues/65992 -## Example +------------------------ +"##, + }, + Lint { + label: "new_uninit", + description: r##"# `new_uninit` -```rust -#![feature(coverage)] +The tracking issue for this feature is: [#63291] -// `foo()` will get coverage instrumentation (by default) -fn foo() { - // ... -} +[#63291]: https://github.com/rust-lang/rust/issues/63291 -#[coverage(off)] -fn bar() { - // ... -} -``` +------------------------ +"##, + }, + 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 { @@ -3572,6 +6595,319 @@ 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] + +[#82901]: https://github.com/rust-lang/rust/issues/82901 + +------------------------ +"##, + }, + 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` @@ -3608,24 +6944,24 @@ of a library. 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) +[`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(box_syntax, rustc_private)] +#![feature(rustc_private)] extern crate rustc_ast; // Load rustc as a plugin to get macros extern crate rustc_driver; -#[macro_use] extern crate rustc_lint; #[macro_use] extern crate rustc_session; -use rustc_driver::plugin::Registry; -use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; 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]); @@ -3633,9 +6969,7 @@ 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, |lint| { - lint.build("item is named 'lintme'").set_span(it.span).emit() - }); + cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span)); } } } @@ -3643,7 +6977,7 @@ impl EarlyLintPass for Pass { #[no_mangle] fn __rustc_plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&TEST_LINT]); - reg.lint_store.register_early_pass(|| box Pass); + reg.lint_store.register_early_pass(|| Box::new(Pass)); } ``` @@ -3677,7 +7011,7 @@ The components of a lint plugin are: 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) +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. @@ -3692,6 +7026,88 @@ 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` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "portable_simd", + description: r##"# `portable_simd` + +The tracking issue for this feature is: [#86656] + +[#86656]: https://github.com/rust-lang/rust/issues/86656 + +------------------------ +"##, + }, + Lint { + label: "powerpc_target_feature", + description: r##"# `powerpc_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "precise_pointer_size_matching", + description: r##"# `precise_pointer_size_matching` + +The tracking issue for this feature is: [#56354] + +[#56354]: https://github.com/rust-lang/rust/issues/56354 + +------------------------ +"##, + }, + Lint { + label: "prelude_2024", + description: r##"# `prelude_2024` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + 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. + +------------------------ +"##, + }, + Lint { label: "print_internals", description: r##"# `print_internals` @@ -3701,6 +7117,123 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { + label: "proc_macro_byte_character", + description: r##"# `proc_macro_byte_character` + +The tracking issue for this feature is: [#115268] + +[#115268]: https://github.com/rust-lang/rust/issues/115268 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_def_site", + description: r##"# `proc_macro_def_site` + +The tracking issue for this feature is: [#54724] + +[#54724]: https://github.com/rust-lang/rust/issues/54724 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_diagnostic", + description: r##"# `proc_macro_diagnostic` + +The tracking issue for this feature is: [#54140] + +[#54140]: https://github.com/rust-lang/rust/issues/54140 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_expand", + description: r##"# `proc_macro_expand` + +The tracking issue for this feature is: [#90765] + +[#90765]: https://github.com/rust-lang/rust/issues/90765 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_hygiene", + description: r##"# `proc_macro_hygiene` + +The tracking issue for this feature is: [#54727] + +[#54727]: https://github.com/rust-lang/rust/issues/54727 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_internals", + description: r##"# `proc_macro_internals` + +The tracking issue for this feature is: [#27812] + +[#27812]: https://github.com/rust-lang/rust/issues/27812 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_quote", + description: r##"# `proc_macro_quote` + +The tracking issue for this feature is: [#54722] + +[#54722]: https://github.com/rust-lang/rust/issues/54722 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_span", + description: r##"# `proc_macro_span` + +The tracking issue for this feature is: [#54725] + +[#54725]: https://github.com/rust-lang/rust/issues/54725 + +------------------------ +"##, + }, + Lint { + label: "proc_macro_tracked_env", + description: r##"# `proc_macro_tracked_env` + +The tracking issue for this feature is: [#99515] + +[#99515]: https://github.com/rust-lang/rust/issues/99515 + +------------------------ +"##, + }, + Lint { + label: "process_exitcode_internals", + description: r##"# `process_exitcode_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "process_internals", + description: r##"# `process_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { label: "profiler_runtime", description: r##"# `profiler_runtime` @@ -3719,41 +7252,204 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { - label: "raw_dylib", - description: r##"# `raw_dylib` + label: "ptr_addr_eq", + description: r##"# `ptr_addr_eq` -The tracking issue for this feature is: [#58713] +The tracking issue for this feature is: [#116324] -[#58713]: https://github.com/rust-lang/rust/issues/58713 +[#116324]: https://github.com/rust-lang/rust/issues/116324 ------------------------ +"##, + }, + Lint { + label: "ptr_alignment_type", + description: r##"# `ptr_alignment_type` -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: [#102070] -```rust,ignore (partial-example) -#![feature(raw_dylib)] +[#102070]: https://github.com/rust-lang/rust/issues/102070 -#[link(name="library", kind="raw-dylib")] -extern { - fn extern_function(x: i32); -} +------------------------ +"##, + }, + Lint { + label: "ptr_as_uninit", + description: r##"# `ptr_as_uninit` -fn main() { - unsafe { - extern_function(14); - } -} -``` +The tracking issue for this feature is: [#75402] + +[#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] + +[#106116]: https://github.com/rust-lang/rust/issues/106116 + +------------------------ +"##, + }, + Lint { + label: "ptr_internals", + description: r##"# `ptr_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "ptr_mask", + description: r##"# `ptr_mask` + +The tracking issue for this feature is: [#98290] + +[#98290]: https://github.com/rust-lang/rust/issues/98290 + +------------------------ +"##, + }, + Lint { + label: "ptr_metadata", + description: r##"# `ptr_metadata` + +The tracking issue for this feature is: [#81513] + +[#81513]: https://github.com/rust-lang/rust/issues/81513 + +------------------------ +"##, + }, + Lint { + label: "ptr_sub_ptr", + description: r##"# `ptr_sub_ptr` + +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 tracking issue for this feature is: [#91126] + +[#91126]: https://github.com/rust-lang/rust/issues/91126 + +------------------------ +"##, + }, + Lint { + label: "pub_crate_should_not_need_unstable_attr", + description: r##"# `pub_crate_should_not_need_unstable_attr` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "raw_os_error_ty", + description: r##"# `raw_os_error_ty` + +The tracking issue for this feature is: [#107792] + +[#107792]: https://github.com/rust-lang/rust/issues/107792 + +------------------------ +"##, + }, + Lint { + label: "raw_os_nonzero", + description: r##"# `raw_os_nonzero` + +The tracking issue for this feature is: [#82363] + +[#82363]: https://github.com/rust-lang/rust/issues/82363 -## Limitations +------------------------ +"##, + }, + Lint { + label: "raw_ref_op", + description: r##"# `raw_ref_op` + +The tracking issue for this feature is: [#64490] + +[#64490]: https://github.com/rust-lang/rust/issues/64490 + +------------------------ +"##, + }, + Lint { + label: "raw_slice_split", + description: r##"# `raw_slice_split` + +The tracking issue for this feature is: [#95595] -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. +[#95595]: https://github.com/rust-lang/rust/issues/95595 -On the `i686-pc-windows-msvc` target, this feature supports only the `cdecl`, `stdcall`, `system`, and `fastcall` -calling conventions. +------------------------ +"##, + }, + Lint { + label: "raw_vec_internals", + description: r##"# `raw_vec_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "read_buf", + description: r##"# `read_buf` + +The tracking issue for this feature is: [#78485] + +[#78485]: https://github.com/rust-lang/rust/issues/78485 + +------------------------ +"##, + }, + Lint { + label: "ready_into_inner", + description: r##"# `ready_into_inner` + +The tracking issue for this feature is: [#101196] + +[#101196]: https://github.com/rust-lang/rust/issues/101196 + +------------------------ +"##, + }, + Lint { + label: "receiver_trait", + description: r##"# `receiver_trait` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "register_tool", + description: r##"# `register_tool` + +The tracking issue for this feature is: [#66079] + +[#66079]: https://github.com/rust-lang/rust/issues/66079 + +------------------------ "##, }, Lint { @@ -3779,6 +7475,103 @@ enum Foo { "##, }, Lint { + label: "repr_simd", + description: r##"# `repr_simd` + +The tracking issue for this feature is: [#27731] + +[#27731]: https://github.com/rust-lang/rust/issues/27731 + +------------------------ +"##, + }, + Lint { + label: "restricted_std", + description: r##"# `restricted_std` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "result_flattening", + description: r##"# `result_flattening` + +The tracking issue for this feature is: [#70142] + +[#70142]: https://github.com/rust-lang/rust/issues/70142 + +------------------------ +"##, + }, + Lint { + label: "result_option_inspect", + description: r##"# `result_option_inspect` + +The tracking issue for this feature is: [#91345] + +[#91345]: https://github.com/rust-lang/rust/issues/91345 + +------------------------ +"##, + }, + Lint { + label: "return_position_impl_trait_in_trait", + description: r##"# `return_position_impl_trait_in_trait` + +The tracking issue for this feature is: [#91611] + +[#91611]: https://github.com/rust-lang/rust/issues/91611 + +------------------------ +"##, + }, + Lint { + label: "return_type_notation", + description: r##"# `return_type_notation` + +The tracking issue for this feature is: [#109417] + +[#109417]: https://github.com/rust-lang/rust/issues/109417 + +------------------------ +"##, + }, + Lint { + label: "riscv_target_feature", + description: r##"# `riscv_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "round_char_boundary", + description: r##"# `round_char_boundary` + +The tracking issue for this feature is: [#93743] + +[#93743]: https://github.com/rust-lang/rust/issues/93743 + +------------------------ +"##, + }, + Lint { + label: "round_ties_even", + description: r##"# `round_ties_even` + +The tracking issue for this feature is: [#96710] + +[#96710]: https://github.com/rust-lang/rust/issues/96710 + +------------------------ +"##, + }, + Lint { label: "rt", description: r##"# `rt` @@ -3788,6 +7581,39 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { + label: "rtm_target_feature", + description: r##"# `rtm_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "rust_cold_cc", + description: r##"# `rust_cold_cc` + +The tracking issue for this feature is: [#97544] + +[#97544]: https://github.com/rust-lang/rust/issues/97544 + +------------------------ +"##, + }, + Lint { + label: "rustc_allow_const_fn_unstable", + description: r##"# `rustc_allow_const_fn_unstable` + +The tracking issue for this feature is: [#69399] + +[#69399]: https://github.com/rust-lang/rust/issues/69399 + +------------------------ +"##, + }, + Lint { label: "rustc_attrs", description: r##"# `rustc_attrs` @@ -3845,6 +7671,326 @@ error: aborting due to 2 previous errors "##, }, Lint { + label: "rustc_private", + description: r##"# `rustc_private` + +The tracking issue for this feature is: [#27812] + +[#27812]: https://github.com/rust-lang/rust/issues/27812 + +------------------------ +"##, + }, + Lint { + label: "rustdoc_internals", + description: r##"# `rustdoc_internals` + +The tracking issue for this feature is: [#90418] + +[#90418]: https://github.com/rust-lang/rust/issues/90418 + +------------------------ +"##, + }, + Lint { + label: "rustdoc_missing_doc_code_examples", + description: r##"# `rustdoc_missing_doc_code_examples` + +The tracking issue for this feature is: [#101730] + +[#101730]: https://github.com/rust-lang/rust/issues/101730 + +------------------------ +"##, + }, + 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` + +The tracking issue for this feature is: [#59359] + +[#59359]: https://github.com/rust-lang/rust/issues/59359 + +------------------------ +"##, + }, + Lint { + label: "set_ptr_value", + description: r##"# `set_ptr_value` + +The tracking issue for this feature is: [#75091] + +[#75091]: https://github.com/rust-lang/rust/issues/75091 + +------------------------ +"##, + }, + Lint { + label: "setgroups", + description: r##"# `setgroups` + +The tracking issue for this feature is: [#90747] + +[#90747]: https://github.com/rust-lang/rust/issues/90747 + +------------------------ +"##, + }, + Lint { + label: "sgx_platform", + description: r##"# `sgx_platform` + +The tracking issue for this feature is: [#56975] + +[#56975]: https://github.com/rust-lang/rust/issues/56975 + +------------------------ +"##, + }, + Lint { + label: "simd_ffi", + description: r##"# `simd_ffi` + +The tracking issue for this feature is: [#27731] + +[#27731]: https://github.com/rust-lang/rust/issues/27731 + +------------------------ +"##, + }, + Lint { + label: "sized_type_properties", + description: r##"# `sized_type_properties` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "slice_as_chunks", + description: r##"# `slice_as_chunks` + +The tracking issue for this feature is: [#74985] + +[#74985]: https://github.com/rust-lang/rust/issues/74985 + +------------------------ +"##, + }, + Lint { + label: "slice_concat_ext", + description: r##"# `slice_concat_ext` + +The tracking issue for this feature is: [#27747] + +[#27747]: https://github.com/rust-lang/rust/issues/27747 + +------------------------ +"##, + }, + Lint { + label: "slice_concat_trait", + description: r##"# `slice_concat_trait` + +The tracking issue for this feature is: [#27747] + +[#27747]: https://github.com/rust-lang/rust/issues/27747 + +------------------------ +"##, + }, + Lint { + label: "slice_first_last_chunk", + description: r##"# `slice_first_last_chunk` + +The tracking issue for this feature is: [#111774] + +[#111774]: https://github.com/rust-lang/rust/issues/111774 + +------------------------ +"##, + }, + Lint { + label: "slice_flatten", + description: r##"# `slice_flatten` + +The tracking issue for this feature is: [#95629] + +[#95629]: https://github.com/rust-lang/rust/issues/95629 + +------------------------ +"##, + }, + Lint { + label: "slice_from_ptr_range", + description: r##"# `slice_from_ptr_range` + +The tracking issue for this feature is: [#89792] + +[#89792]: https://github.com/rust-lang/rust/issues/89792 + +------------------------ +"##, + }, + Lint { + label: "slice_group_by", + description: r##"# `slice_group_by` + +The tracking issue for this feature is: [#80552] + +[#80552]: https://github.com/rust-lang/rust/issues/80552 + +------------------------ +"##, + }, + Lint { + label: "slice_index_methods", + description: r##"# `slice_index_methods` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "slice_internals", + description: r##"# `slice_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "slice_iter_mut_as_mut_slice", + description: r##"# `slice_iter_mut_as_mut_slice` + +The tracking issue for this feature is: [#93079] + +[#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] + +[#54279]: https://github.com/rust-lang/rust/issues/54279 + +------------------------ +"##, + }, + Lint { + label: "slice_pattern", + description: r##"# `slice_pattern` + +The tracking issue for this feature is: [#56345] + +[#56345]: https://github.com/rust-lang/rust/issues/56345 + +------------------------ +"##, + }, + Lint { + label: "slice_ptr_get", + description: r##"# `slice_ptr_get` + +The tracking issue for this feature is: [#74265] + +[#74265]: https://github.com/rust-lang/rust/issues/74265 + +------------------------ +"##, + }, + Lint { + label: "slice_ptr_len", + description: r##"# `slice_ptr_len` + +The tracking issue for this feature is: [#71146] + +[#71146]: https://github.com/rust-lang/rust/issues/71146 + +------------------------ +"##, + }, + Lint { + label: "slice_range", + description: r##"# `slice_range` + +The tracking issue for this feature is: [#76393] + +[#76393]: https://github.com/rust-lang/rust/issues/76393 + +------------------------ +"##, + }, + Lint { + label: "slice_split_at_unchecked", + description: r##"# `slice_split_at_unchecked` + +The tracking issue for this feature is: [#76014] + +[#76014]: https://github.com/rust-lang/rust/issues/76014 + +------------------------ +"##, + }, + Lint { + label: "slice_swap_unchecked", + description: r##"# `slice_swap_unchecked` + +The tracking issue for this feature is: [#88539] + +[#88539]: https://github.com/rust-lang/rust/issues/88539 + +------------------------ +"##, + }, + Lint { + label: "slice_take", + description: r##"# `slice_take` + +The tracking issue for this feature is: [#62280] + +[#62280]: https://github.com/rust-lang/rust/issues/62280 + +------------------------ +"##, + }, + Lint { + label: "solid_ext", + description: r##"# `solid_ext` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "sort_floats", + description: r##"# `sort_floats` + +The tracking issue for this feature is: [#93396] + +[#93396]: https://github.com/rust-lang/rust/issues/93396 + +------------------------ +"##, + }, + Lint { label: "sort_internals", description: r##"# `sort_internals` @@ -3854,6 +8000,184 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { + label: "spec_option_partial_eq", + description: r##"# `spec_option_partial_eq` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "specialization", + description: r##"# `specialization` + +The tracking issue for this feature is: [#31844] + +[#31844]: https://github.com/rust-lang/rust/issues/31844 + +------------------------ +"##, + }, + Lint { + label: "split_array", + description: r##"# `split_array` + +The tracking issue for this feature is: [#90091] + +[#90091]: https://github.com/rust-lang/rust/issues/90091 + +------------------------ +"##, + }, + Lint { + label: "split_as_slice", + description: r##"# `split_as_slice` + +The tracking issue for this feature is: [#96137] + +[#96137]: https://github.com/rust-lang/rust/issues/96137 + +------------------------ +"##, + }, + Lint { + label: "sse4a_target_feature", + description: r##"# `sse4a_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "staged_api", + description: r##"# `staged_api` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "start", + description: r##"# `start` + +The tracking issue for this feature is: [#29633] + +[#29633]: https://github.com/rust-lang/rust/issues/29633 + +------------------------ + +Allows you to mark a function as the entry point of the executable, which is +necessary in `#![no_std]` environments. + +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: + +```rust,ignore (only-for-syntax-highlight) +# let _: +fn(isize, *const *const u8) -> isize +# ; +``` + +This feature should not be confused with the `start` *lang item* which is +defined by the `std` crate and is written `#[lang = "start"]`. + +## Usage together with the `std` crate + +`#[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 +#![feature(start)] + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +``` + +Unwinding the stack past the `#[start]` function is currently considered +Undefined Behavior (for any unwinding implementation): + +```rust,ignore (UB) +#![feature(start)] + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + std::panic::catch_unwind(|| { + panic!(); // panic safely gets caught or safely aborts execution + }); + + panic!(); // UB! + + 0 +} +``` +"##, + }, + Lint { + label: "std_internals", + description: r##"# `std_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "stdio_makes_pipe", + description: r##"# `stdio_makes_pipe` + +The tracking issue for this feature is: [#98288] + +[#98288]: https://github.com/rust-lang/rust/issues/98288 + +------------------------ +"##, + }, + Lint { + label: "stdsimd", + description: r##"# `stdsimd` + +The tracking issue for this feature is: [#48556] + +[#48556]: https://github.com/rust-lang/rust/issues/48556 + +------------------------ +"##, + }, + Lint { + label: "step_trait", + description: r##"# `step_trait` + +The tracking issue for this feature is: [#42168] + +[#42168]: https://github.com/rust-lang/rust/issues/42168 + +------------------------ +"##, + }, + Lint { + label: "stmt_expr_attributes", + description: r##"# `stmt_expr_attributes` + +The tracking issue for this feature is: [#15701] + +[#15701]: https://github.com/rust-lang/rust/issues/15701 + +------------------------ +"##, + }, + Lint { label: "str_internals", description: r##"# `str_internals` @@ -3863,6 +8187,186 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, Lint { + label: "str_split_inclusive_remainder", + description: r##"# `str_split_inclusive_remainder` + +The tracking issue for this feature is: [#77998] + +[#77998]: https://github.com/rust-lang/rust/issues/77998 + +------------------------ +"##, + }, + Lint { + label: "str_split_remainder", + description: r##"# `str_split_remainder` + +The tracking issue for this feature is: [#77998] + +[#77998]: https://github.com/rust-lang/rust/issues/77998 + +------------------------ +"##, + }, + Lint { + label: "str_split_whitespace_remainder", + description: r##"# `str_split_whitespace_remainder` + +The tracking issue for this feature is: [#77998] + +[#77998]: https://github.com/rust-lang/rust/issues/77998 + +------------------------ +"##, + }, + Lint { + label: "strict_provenance", + description: r##"# `strict_provenance` + +The tracking issue for this feature is: [#95228] + +[#95228]: https://github.com/rust-lang/rust/issues/95228 +----- + +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() { + 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` + +The tracking issue for this feature is: [#99108] + +[#99108]: https://github.com/rust-lang/rust/issues/99108 + +------------------------ +"##, + }, + Lint { + label: "string_deref_patterns", + description: r##"# `string_deref_patterns` + +The tracking issue for this feature is: [#87121] + +[#87121]: https://github.com/rust-lang/rust/issues/87121 + +------------------------ +"##, + }, + Lint { + label: "string_extend_from_within", + description: r##"# `string_extend_from_within` + +The tracking issue for this feature is: [#103806] + +[#103806]: https://github.com/rust-lang/rust/issues/103806 + +------------------------ +"##, + }, + Lint { + label: "string_remove_matches", + description: r##"# `string_remove_matches` + +The tracking issue for this feature is: [#72826] + +[#72826]: https://github.com/rust-lang/rust/issues/72826 + +------------------------ +"##, + }, + Lint { + label: "structural_match", + description: r##"# `structural_match` + +The tracking issue for this feature is: [#31434] + +[#31434]: https://github.com/rust-lang/rust/issues/31434 + +------------------------ +"##, + }, + Lint { + label: "sync_unsafe_cell", + description: r##"# `sync_unsafe_cell` + +The tracking issue for this feature is: [#95439] + +[#95439]: https://github.com/rust-lang/rust/issues/95439 + +------------------------ +"##, + }, + Lint { + label: "target_feature_11", + description: r##"# `target_feature_11` + +The tracking issue for this feature is: [#69098] + +[#69098]: https://github.com/rust-lang/rust/issues/69098 + +------------------------ +"##, + }, + Lint { + label: "tbm_target_feature", + description: r##"# `tbm_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "tcp_linger", + description: r##"# `tcp_linger` + +The tracking issue for this feature is: [#88494] + +[#88494]: https://github.com/rust-lang/rust/issues/88494 + +------------------------ +"##, + }, + Lint { + label: "tcp_quickack", + description: r##"# `tcp_quickack` + +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 + +------------------------ +"##, + }, + Lint { label: "test", description: r##"# `test` @@ -4025,6 +8529,57 @@ 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 { label: "thread_local_internals", description: r##"# `thread_local_internals` @@ -4034,6 +8589,28 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, 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 + +------------------------ +"##, + }, + Lint { label: "trace_macros", description: r##"# `trace_macros` @@ -4077,6 +8654,17 @@ note: trace_macro "##, }, 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 { label: "trait_alias", description: r##"# `trait_alias` @@ -4146,6 +8734,28 @@ 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 { label: "transparent_unions", description: r##"# `transparent_unions` @@ -4233,6 +8843,59 @@ 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 { label: "try_blocks", description: r##"# `try_blocks` @@ -4267,6 +8930,92 @@ assert!(result.is_err()); "##, }, Lint { + 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` @@ -4304,6 +9053,39 @@ fn main () { "##, }, 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` @@ -4319,7 +9101,7 @@ The `unboxed_closures` feature allows you to write functions using the `"rust-ca 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*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html +[`Fn*`]: ../../std/ops/trait.Fn.html ```rust #![feature(unboxed_closures)] @@ -4333,6 +9115,200 @@ 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: [#76915] + +[#76915]: https://github.com/rust-lang/rust/issues/76915 + +------------------------ +"##, + }, + Lint { + label: "unix_socket_peek", + description: r##"# `unix_socket_peek` + +The tracking issue for this feature is: [#76923] + +[#76923]: https://github.com/rust-lang/rust/issues/76923 + +------------------------ +"##, + }, + Lint { + label: "unnamed_fields", + description: r##"# `unnamed_fields` + +The tracking issue for this feature is: [#49804] + +[#49804]: https://github.com/rust-lang/rust/issues/49804 + +------------------------ +"##, + }, + Lint { + label: "unsafe_cell_from_mut", + description: r##"# `unsafe_cell_from_mut` + +The tracking issue for this feature is: [#111645] + +[#111645]: https://github.com/rust-lang/rust/issues/111645 + +------------------------ +"##, + }, + 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. + +------------------------ +"##, + }, + Lint { + label: "unsize", + description: r##"# `unsize` + +The tracking issue for this feature is: [#18598] + +[#18598]: https://github.com/rust-lang/rust/issues/18598 + +------------------------ +"##, + }, + Lint { + label: "unsized_fn_params", + description: r##"# `unsized_fn_params` + +The tracking issue for this feature is: [#48055] + +[#48055]: https://github.com/rust-lang/rust/issues/48055 + +------------------------ +"##, + }, + Lint { label: "unsized_locals", description: r##"# `unsized_locals` @@ -4543,6 +9519,17 @@ fn main() { "##, }, 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` @@ -4552,6 +9539,149 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, 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` @@ -4579,6 +9709,59 @@ This feature is internal to the Rust compiler and is not intended for general us "##, }, 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` @@ -4587,10 +9770,95 @@ This feature is internal to the Rust compiler and is not intended for general us ------------------------ "##, }, + Lint { + label: "with_negative_coherence", + description: r##"# `with_negative_coherence` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "wrapping_int_impl", + description: r##"# `wrapping_int_impl` + +The tracking issue for this feature is: [#32463] + +[#32463]: https://github.com/rust-lang/rust/issues/32463 + +------------------------ +"##, + }, + Lint { + label: "wrapping_next_power_of_two", + description: r##"# `wrapping_next_power_of_two` + +The tracking issue for this feature is: [#32463] + +[#32463]: https://github.com/rust-lang/rust/issues/32463 + +------------------------ +"##, + }, + Lint { + label: "write_all_vectored", + description: r##"# `write_all_vectored` + +The tracking issue for this feature is: [#70436] + +[#70436]: https://github.com/rust-lang/rust/issues/70436 + +------------------------ +"##, + }, + Lint { + label: "yeet_desugar_details", + description: r##"# `yeet_desugar_details` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "yeet_expr", + description: r##"# `yeet_expr` + +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<String, i32> { + do yeet 4; +} +assert_eq!(foo(), Err(4)); + +fn bar() -> Option<String> { + 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 @@ -4598,6 +9866,33 @@ 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", description: r##"Checks for `foo = bar; bar = foo` sequences."##, }, @@ -4611,22 +9906,50 @@ or 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", description: r##"Checks for usage of `as` conversions. 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` patterns."##, @@ -4641,14 +9964,17 @@ patterns."##, 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,14 +9985,18 @@ The formula for detecting if an expression of the type `_ <bit_op> 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", @@ -4674,11 +10004,6 @@ table: `_.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", description: r##"Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category."##, }, @@ -4698,21 +10023,38 @@ expression, statements or conditions that use closures with blocks."##, 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., contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.) has been borrowed directly."##, }, Lint { label: "clippy::borrowed_box", - description: r##"Checks for use of `&Box<T>` anywhere in the code. + description: r##"Checks for usage of `&Box<T>` 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<T>` where T is a collection such as Vec anywhere in the code. + description: r##"Checks for usage of `Box<T>` 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::<T>::default()`."##, + }, + Lint { label: "clippy::boxed_local", description: r##"Checks for usage of `Box<T>` where an unboxed `T` would work fine."##, @@ -4727,6 +10069,11 @@ moved out of the blocks."##, 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()`."##, }, @@ -4741,22 +10088,41 @@ moved out of the blocks."##, 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."##, }, @@ -4776,10 +10142,6 @@ or any 64-bit integer to `f64`."##, 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 type. In this case, negative values wrap around to large positive values, @@ -4787,6 +10149,14 @@ 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 to `u8` and suggests using a byte literal instead."##, @@ -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`"##, @@ -4857,6 +10226,15 @@ Note that this lint is not intended to find _all_ cases where nested match patte 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 rewritten with `match` and `cmp`."##, @@ -4872,6 +10250,10 @@ and suggests using `.is_empty()` where applicable."##, `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 @@ -4895,6 +10280,15 @@ parameter in `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!` macros." 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", description: r##"Checks for usage of unconstrained numeric literals which may cause default numeric fallback in type inference. @@ -4910,6 +10304,10 @@ See [RFC0212](https://github.com/rust-lang/rfcs/blob/master/text/0212-restore-in 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 with `#[rustfmt::skip]`."##, @@ -4924,22 +10322,46 @@ field that is not a valid semantic version."##, 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,7 +10380,10 @@ 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", @@ -4966,6 +10391,11 @@ See also: [`non_ascii_idents`]. 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", description: r##"Checks for the presence of `_`, `::` or camel-case words outside ticks in documentation."##, @@ -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_ref", - description: r##"Checks for calls to `std::mem::drop` with a reference -instead of an owned value."##, + 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::duplicate_mod", + description: r##"Checks for files that are included as modules multiple times."##, }, Lint { label: "clippy::duplicate_underscore_argument", @@ -5014,6 +10449,10 @@ from other `Duration` methods."##, 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. @@ -5022,11 +10461,19 @@ 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 `repr(isize/usize)` and have values that don't fit into an `i32`."##, @@ -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,7 +10536,7 @@ 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", @@ -5090,6 +10544,10 @@ etc., and suggests to use `unwrap_or_else` instead"##, 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 and suggests the use of `.enumerate()`."##, @@ -5127,6 +10585,10 @@ replaced with `(e)print!()` / `(e)println!()`"##, 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()`"##, }, @@ -5144,6 +10606,10 @@ with Default::default()."##, 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."##, + 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_copy", - description: r##"Checks for calls to `std::mem::forget` with a value that -derives the Copy trait"##, - }, - 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::<String>()`."##, }, Lint { label: "clippy::format_in_format_args", @@ -5231,6 +10691,15 @@ 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` trait."##, @@ -5240,6 +10709,10 @@ trait."##, 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)`"##, }, @@ -5251,16 +10724,25 @@ 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,13 +10767,21 @@ 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."##, }, @@ -5306,10 +10796,25 @@ algorithm (`SipHash`)."##, 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<Target = i32>` 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 can be expressed using built-in methods to improve accuracy @@ -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", @@ -5371,6 +10876,12 @@ or tuple struct where a `let` will suffice."##, 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)]`, unless the annotated function is empty or simply panics."##, @@ -5395,16 +10906,6 @@ 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", @@ -5412,6 +10913,12 @@ attempted."##, 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", description: r##"This lint checks for invalid usages of `ptr::null`."##, }, @@ -5432,10 +10939,20 @@ necessary. Only integer types are checked."##, 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 create a `Vec`."##, @@ -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,7 +10977,7 @@ 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 { @@ -5463,8 +10985,37 @@ create a `Vec`."##, 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().<func>()` 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", @@ -5492,10 +11043,29 @@ are too large."##, `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 the argument type is `Copy` and large enough to be worth considering @@ -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 _ = <expr>` -where expr has a type that implements `Drop`"##, + label: "clippy::let_underscore_future", + description: r##"Checks for `let _ = <expr>` 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 _ = <expr>` where expr is `#[must_use]`"##, }, + Lint { + label: "clippy::let_underscore_untyped", + description: r##"Checks for `let _ = <expr>` 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", @@ -5565,23 +11148,74 @@ cannot be represented as the underlying type without loss."##, 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::<T>() * 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 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 != <float>::INFINITY && x != <float>::NEG_INFINITY`)."##, + }, + Lint { + label: "clippy::manual_is_infinite", + description: r##"Checks for manual `is_infinite` reimplementations +(i.e., `x == <float>::INFINITY || x == <float>::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", @@ -5589,6 +11223,10 @@ where only the `Some` or `Ok` variant of the iterator element is used."##, 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."##, }, @@ -5602,28 +11240,66 @@ slices that could be optimized by having a memcpy."##, 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::<T>()` 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 single character."##, @@ -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", @@ -5719,9 +11398,14 @@ and take drastic actions like `panic!`."##, 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", @@ -5739,6 +11423,13 @@ and take drastic actions like `panic!`."##, 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", description: r##"Checks for expressions where `std::cmp::min` and `max` are used to clamp values, but switched so that the result is constant."##, @@ -5752,17 +11443,37 @@ used to clamp values, but switched so that the result is constant."##, 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", @@ -5775,6 +11486,10 @@ in the `enforce-import-renames` config option."##, 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, or trait method impl is not `#[inline]`."##, @@ -5789,6 +11504,17 @@ may panic and warns if there is no `# Panics` section."##, 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", description: r##"Warns for mistyped suffix in literals"##, @@ -5799,8 +11525,14 @@ unsafe functions and warns if there is no `# Safety` section."##, 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 @@ -5828,6 +11561,10 @@ used."##, 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 `#[must_use]` attribute, but return something not already marked @@ -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<X>` where an atomic will do."##, + description: r##"Checks for usage of `Mutex<X>` where an atomic will do."##, }, Lint { label: "clippy::mutex_integer", - description: r##"Checks for usages of `Mutex<X>` where `X` is an integral + description: r##"Checks for usage of `Mutex<X>` where `X` is an integral type."##, }, Lint { label: "clippy::naive_bytecount", description: r##"Checks for naive byte counts"## }, @@ -5876,7 +11617,7 @@ 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 { @@ -5885,16 +11626,27 @@ a lazy and."##, 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", description: r##"Checks for address of operations (`&`) that are going to 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", description: r##"Checks for functions collecting an iterator when collect is not needed."##, @@ -5910,12 +11662,17 @@ 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 with an initializer."##, @@ -5926,17 +11683,42 @@ with an initializer."##, 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", description: r##"Checks for functions taking arguments by value, but not 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"##, }, @@ -5946,12 +11728,24 @@ body."##, 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)."##, }, @@ -5994,14 +11788,34 @@ implementation of 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."##, }, @@ -6033,12 +11847,20 @@ that make no sense."##, 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 taken to satisfy a bound @@ -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<Option<_>>` in function signatures and type + description: r##"Checks for usage of `Option<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,25 +11921,49 @@ 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", description: r##"Checks for patterns that aren't exact representations of the types they are applied to. @@ -6133,6 +11985,10 @@ this lint can still be used to highlight areas of interest and ensure a good und 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 an array element is a binary operator expression and it lies on two lines."##, @@ -6148,6 +12004,11 @@ 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", description: r##"This lint warns about the use of literals as `print!`/`println!` args."##, }, @@ -6173,16 +12034,20 @@ 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 { label: "clippy::ptr_offset_with_cast", @@ -6193,11 +12058,27 @@ 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(<loc>)` with `in`."##, + }, + Lint { + label: "clippy::pub_without_shorthand", + description: r##"Checks for usage of `pub(<loc>)` without `in`. + +Note: As you cannot write a module's path in `pub(<loc>)`, 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 the upper bound, e.g., `x..=(y-1)`."##, @@ -6220,10 +12101,49 @@ upper bound, e.g., `x..(y+1)`."##, label: "clippy::rc_buffer", description: r##"Checks for `Rc<T>` and `Arc<T>` 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<Mutex<T>>`."## }, 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", @@ -6247,6 +12167,10 @@ are defined."##, 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."##, }, @@ -6260,6 +12184,14 @@ argument and can be replaced by referencing the method directly."##, 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,19 +12215,22 @@ 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."##, }, @@ -6314,10 +12249,19 @@ they are equivalent to `1`. (Related discussion in [rust-clippy#7306](https://gi 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", @@ -6361,6 +12305,16 @@ one from a trait, another not from trait."##, `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", description: r##"Checks for explicit self-assignments."##, }, @@ -6370,7 +12324,7 @@ 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", @@ -6378,6 +12332,15 @@ one from a trait, another not from trait."##, `()` 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. To enforce separated literal suffix style, @@ -6421,8 +12384,31 @@ 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", @@ -6430,6 +12416,11 @@ information) instead of an inherent implementation."##, 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", description: r##"Checks for string methods that receive a single-character `str` as an argument, e.g., `_.split(x)`."##, @@ -6445,7 +12436,12 @@ 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", @@ -6453,12 +12449,21 @@ will usually suffice."##, 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::<T>` or `size_of_val::<T>` 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", description: r##"Checks for usage of `_.skip_while(condition).next()`."##, }, @@ -6469,10 +12474,18 @@ 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`."##, }, @@ -6502,6 +12515,10 @@ match."##, that contain only ASCII characters."##, }, Lint { + label: "clippy::string_lit_chars_any", + description: r##"Checks for `<string_lit>.chars().any(|i| i == c)`."##, + }, + Lint { label: "clippy::string_slice", description: r##"Checks for slice operations on strings"##, }, @@ -6532,10 +12549,19 @@ 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` is followed immediately by a newline or the `else` seems to be missing."##, @@ -6562,12 +12588,24 @@ of binary operators nearby."##, 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 { @@ -6634,6 +12673,15 @@ syntax specifications for trait bounds are used simultaneously."##, 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`"##, }, @@ -6647,6 +12695,11 @@ from a reference to a reference."##, 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."##, }, @@ -6655,6 +12708,10 @@ from a reference to a reference."##, 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) creation (with `Regex::new`, `RegexBuilder::new`, or `RegexSet::new`)."##, @@ -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 `<Box<dyn Any> 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", @@ -6706,6 +12789,11 @@ 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", description: r##"Checks for passing a unit value as an argument to a function without using a unit literal (`()`)."##, @@ -6723,23 +12811,40 @@ 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<T>` where `T` implements `Sized` + +The lint ignores `Box<T>` 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::<Vec<String>>().join()` on iterators."##, + }, + Lint { label: "clippy::unnecessary_lazy_evaluations", description: r##"As the counterpart to `or_fun_call`, this lint looks for unnecessary lazily evaluated closures on `Option` and `Result`. @@ -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", @@ -6763,15 +12877,33 @@ requires an immutable reference."##, 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", description: r##"Checks for imports ending in `::{self}`."##, }, 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", description: r##"Checks for unnecessary calls to [`ToOwned::to_owned`](https://doc.rust-lang.org/std/borrow/trait.ToOwned.html#tymethod.to_owned) and other `to_owned`-like functions."##, @@ -6855,10 +12987,24 @@ types have different ABI, size or alignment."##, 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<Box<T>>` where T: Sized anywhere in the code. + description: r##"Checks for usage of `Vec<Box<T>>` 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 e475c5cd66b..da5a951f0b7 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, @@ -228,12 +235,30 @@ impl ImportAssets { self.search_for(sema, None, prefer_no_std) } - pub fn path_fuzzy_name_to_exact(&mut self, case_sensitive: bool) { + /// 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); + } + } + + /// 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); @@ -623,7 +648,7 @@ impl ImportCandidate { fuzzy_name: String, sema: &Semantics<'_, RootDatabase>, ) -> Option<Self> { - 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 9be1d366349..a0cfd3836dd 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<ast::Rename>, +) { 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 b92e367f7e1..01d2f1970c3 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 27b6321f3a7..ff84e9ffaee 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 3f7a3ec2d0f..67ed44f08b7 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/symbol_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs index f699f999baf..3e89159c2c6 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 c7d5f3613d4..c8cf87d3c20 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<ClippyLint> = Vec::new(); let mut clippy_groups: std::collections::BTreeMap<String, Vec<String>> = 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/src/handlers/field_shorthand.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/field_shorthand.rs index 3b69640af9b..9ed8199ae4d 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 235062bf531..85dbb7e6f26 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 @@ -113,6 +113,31 @@ fn some_fn() { } "#, ); + + 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; +} +"#, + ); } #[test] @@ -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` @@ -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/mismatched_arg_count.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index 8265e0b1c11..06ba13bcc55 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<const N1: &'static str, const N2: bool>( - a: u8, - b: i8, + _a: u8, + _b: i8, ) {} fn f() { @@ -376,8 +371,8 @@ fn f() { #[rustc_legacy_const_generics(1, 3)] fn b<const N1: u8, const N2: u8>( - 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 acc31cd117a..c09be3fee7e 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<Vec<Ass let root = ctx.sema.db.parse_or_expand(d.file); - let current_module = match &d.field_list_parent { - Either::Left(ptr) => 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<Vec<Ass )]) }; - match &d.field_list_parent { - Either::Left(record_expr) => { - 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(); @@ -152,8 +149,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass old_field_list.syntax(), ) } - Either::Right(record_pat) => { - 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 +286,7 @@ fn x(a: S) { struct S { s: u32 } fn x(a: S) { let S { ref s } = a; + _ = s; } ", ) @@ -626,7 +623,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 06b03d3d198..84267d3d906 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 @@ -19,6 +19,7 @@ pub(crate) fn missing_match_arms( mod tests { use crate::tests::check_diagnostics; + #[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) @@ -564,6 +565,7 @@ fn bang(never: !) { r#" enum Option<T> { Some(T), None } +#[allow(unused)] fn main() { // `Never` is deliberately not defined so that it's an uninferred type. match Option::<Never>::None { @@ -719,7 +721,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 +903,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 70b26009bae..0f695b2745a 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 3aa4aa97026..886aefeb575 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 d056e5c85cc..ee096a100aa 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<usize> for Foo { type Output = (i32, u8); - fn index(&self, index: usize) -> &(i32, u8) { + fn index(&self, _index: usize) -> &(i32, u8) { &(5, 2) } } impl IndexMut<usize> 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; } "#, ); 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 290c16c9d24..ee8a9c95793 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<Vec<Assist>> { // 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 c44d28e77f6..a828b8b4fd2 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 083ef3e8dc1..d15233d15c2 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/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 15bd28c00df..14454fe8dc4 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::<ast::Expr>(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::<ast::Expr>( + 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<Vec<Assist>> { 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::<ast::Expr>() { + 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]) {} "#, ); } @@ -279,7 +283,7 @@ impl core::ops::Deref for Foo { fn main() { test($0Foo); } -fn test(arg: &Bar) {} +fn test(_arg: &Bar) {} "#, r#" struct Foo; @@ -291,7 +295,7 @@ impl core::ops::Deref for Foo { fn main() { test(&Foo); } -fn test(arg: &Bar) {} +fn test(_arg: &Bar) {} "#, ); } @@ -305,7 +309,7 @@ fn main() { } struct Test; impl Test { - fn call_by_ref(&self, arg: &i32) {} + fn call_by_ref(&self, _arg: &i32) {} } "#, r#" @@ -314,7 +318,7 @@ fn main() { } struct Test; impl Test { - fn call_by_ref(&self, arg: &i32) {} + fn call_by_ref(&self, _arg: &i32) {} } "#, ); @@ -345,7 +349,7 @@ macro_rules! thousand { 1000_u64 }; } -fn test(foo: &u64) {} +fn test(_foo: &u64) {} fn main() { test($0thousand!()); } @@ -356,7 +360,7 @@ macro_rules! thousand { 1000_u64 }; } -fn test(foo: &u64) {} +fn test(_foo: &u64) {} fn main() { test(&thousand!()); } @@ -369,12 +373,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 +415,7 @@ fn div(x: i32, y: i32) -> Option<i32> { fn f<const N: u64>() -> Rate<N> { // 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 +430,7 @@ fn div(x: i32, y: i32) -> Option<i32> { check_diagnostics( r#" pub struct Rate<T, const NOM: u32, const DENOM: u32>(T); - fn run(t: Rate<u32, 1, 1>) { + fn run(_t: Rate<u32, 1, 1>) { } fn main() { run(Rate::<_, _, _>(5)); @@ -650,7 +654,7 @@ fn h() { r#" struct X<T>(T); -fn foo(x: X<Unknown>) {} +fn foo(_x: X<Unknown>) {} fn test1() { // Unknown might be `i32`, so we should not emit type mismatch here. foo(X(42)); 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 4af67227115..4e215a89d79 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>() -> 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 00000000000..28ccf474b40 --- /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 ebe197a6790..fe5567544e8 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -56,6 +56,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; @@ -368,6 +369,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/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index 37a17762216..ac15b6aba61 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/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 21934b9480e..e0b64fe7988 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::<Vec<_>>(), + ), } - 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::<Vec<_>>(), - ) }) .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 f72ce37d1d9..d0a02fd0dba 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 81d6db564ff..e54bc48d555 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -5266,38 +5266,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<T, U>(x: T) -> U; - "##]], + fn arith_offset<T>(dst: *const T, offset: isize) -> *const T; + } + ``` + + As with any other FFI functions, these are always `unsafe` to call. + + "#]], ) } 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 12e46c0f883..4152e606755 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 @@ -484,7 +484,7 @@ fn main() { file_id: FileId( 1, ), - range: 10739..10747, + range: 10752..10760, }, ), tooltip: "", @@ -497,7 +497,7 @@ fn main() { file_id: FileId( 1, ), - range: 10771..10775, + range: 10784..10788, }, ), tooltip: "", @@ -522,7 +522,7 @@ fn main() { file_id: FileId( 1, ), - range: 10739..10747, + range: 10752..10760, }, ), tooltip: "", @@ -535,7 +535,7 @@ fn main() { file_id: FileId( 1, ), - range: 10771..10775, + range: 10784..10788, }, ), tooltip: "", @@ -560,7 +560,7 @@ fn main() { file_id: FileId( 1, ), - range: 10739..10747, + range: 10752..10760, }, ), tooltip: "", @@ -573,7 +573,7 @@ fn main() { file_id: FileId( 1, ), - range: 10771..10775, + range: 10784..10788, }, ), tooltip: "", diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index aee03d218ad..2320c95b4a1 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/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index 2d528c64255..07cdddd15f8 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<Runnable> { - 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/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs index bb01c81d66f..dd72484b380 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 b40509715ba..d21850bcff3 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 2f6332abd25..3802978f494 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 2934d26674d..d784321c7c7 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<T: Internable> Interned<T> { // - 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<str> { // - 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/mbe/src/expander.rs b/src/tools/rust-analyzer/crates/mbe/src/expander.rs index f2d89d3efe5..908048c9904 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 9d886a1c979..a439c9c50d6 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 09e62c35278..efb326323f9 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/grammar/params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs index 74eae9151a2..846da28cb01 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 36c52953a02..b9e7566fdf9 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 c155e8aaf67..fcfd1a50719 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 2c47e3d086d..57005a6834c 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 00000000000..7603c9099da --- /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 00000000000..b2d06e490bd --- /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 00000000000..e8d8ff8cefb --- /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 00000000000..e74847137b1 --- /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 00000000000..1b4424ba5c7 --- /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 00000000000..1b78ffc28a0 --- /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 00000000000..b1e1364d4c2 --- /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 00000000000..291f99d8020 --- /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 00000000000..0cd1747208e --- /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 00000000000..2499516d3fa --- /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 c848ac368e4..fd20ca57ac6 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 b54930f5e69..65460d02cb2 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 66e58cc298f..07172a4ecc0 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 454ee0a5f61..15f52c113c1 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 00000000000..39e35a81ee2 --- /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 00000000000..0adf7b8d2f0 --- /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/project-model/src/build_scripts.rs b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs index fb0f3ab7d17..68cd40c040b 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 e47808a2cc9..ca3d6e0596c 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<String, String>, pub invocation_strategy: InvocationStrategy, pub invocation_location: InvocationLocation, + /// Optional path to use instead of `target` when building + pub target_dir: Option<PathBuf>, } pub type Package = Idx<PackageData>; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index 7410f0a3a66..c85b3e53cda 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml @@ -23,7 +23,7 @@ anyhow = "1.0.62" crossbeam-channel = "0.5.5" dissimilar = "1.0.4" itertools = "0.10.5" -scip = "0.1.1" +scip = "0.3.1" lsp-types = { version = "=0.94.0", features = ["proposed"] } parking_lot = "0.12.1" xflags = "0.3.0" @@ -57,6 +57,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 +68,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 @@ -89,4 +91,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 2fa14fc7e28..a7d0a0b0dfc 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 dcb3ca6581c..230ff5f9b86 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 @@ -846,9 +846,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 +886,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 419440b6df7..fe5022f8606 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<PathBuf>, + pub config_path: Option<PathBuf>, } 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 8c056fff000..30e11402cd8 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 ea3a21241cb..c8df4255d96 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<usize> = "null", /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. @@ -470,6 +480,14 @@ config_data! { /// tests or binaries. For example, it may be `--release`. runnables_extraArgs: Vec<String> = "[]", + /// 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<TargetDirectory> = "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 +583,7 @@ pub struct Config { data: ConfigData, detached_files: Vec<AbsPathBuf>, snippets: Vec<Snippet>, + is_visual_studio_code: bool, } type ParallelCachePrimingNumThreads = u8; @@ -755,11 +774,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<AbsPathBuf>, + is_visual_studio_code: bool, ) -> Self { Config { caps, @@ -769,6 +791,7 @@ impl Config { root_path, snippets: Default::default(), workspace_roots, + is_visual_studio_code, } } @@ -1248,6 +1271,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 +1344,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<PathBuf> { + 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 } @@ -1444,6 +1479,7 @@ 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), @@ -1667,6 +1703,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 +2057,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 +2493,19 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json }, ], }, + "Option<TargetDirectory>" => set! { + "anyOf": [ + { + "type": "null" + }, + { + "type": "boolean" + }, + { + "type": "string" + }, + ], + }, _ => panic!("missing entry for {ty}: {default}"), } @@ -2555,8 +2618,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 +2634,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 +2650,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 +2666,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 731580557c2..f8bc66ff8e7 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 b8a1a39be19..06c27332d44 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 5a11012b93c..2c402552919 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 { @@ -173,6 +174,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 { 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 23074493aee..aca91570f7c 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 @@ -443,15 +443,17 @@ pub(crate) fn inlay_hint( file_id: FileId, inlay_hint: InlayHint, ) -> Cancellable<lsp_types::InlayHint> { + 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 { 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 e49b5768fa4..106b99cb935 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 8b5c92c6602..56b5fcef3c2 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!( 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 00000000000..a313507bff3 --- /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.18.0" } +ra-ap-rustc_parse_format = { version = "0.14.0", default-features = false } +ra-ap-rustc_index = { version = "0.18.0", default-features = false } +ra-ap-rustc_abi = { version = "0.18.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 00000000000..13fcbc49193 --- /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/stdx/src/anymap.rs b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs new file mode 100644 index 00000000000..fd44e6c6d0f --- /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<A> = HashMap<TypeId, Box<A>, BuildHasherDefault<TypeIdHasher>>; + +/// 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<dyn Any + Send>`) to add those +/// auto traits. +/// +/// Cumulatively, there are thus six forms of map: +/// +/// - <code>[Map]<dyn [core::any::Any]></code>, +/// also spelled [`AnyMap`] for convenience. +/// - <code>[Map]<dyn [core::any::Any] + Send></code> +/// - <code>[Map]<dyn [core::any::Any] + Send + Sync></code> +/// - <code>[Map]<dyn [CloneAny]></code> +/// - <code>[Map]<dyn [CloneAny] + Send></code> +/// - <code>[Map]<dyn [CloneAny] + Send + Sync></code> +/// +/// ## Example +/// +/// (Here using the [`AnyMap`] convenience alias; the first line could use +/// <code>[anymap::Map][Map]::<[core::any::Any]>::new()</code> 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<A: ?Sized + Downcast = dyn Any> { + raw: RawMap<A>, +} + +/// The most common type of `Map`: just using `Any`; <code>[Map]<dyn [Any]></code>. +/// +/// Why is this a separate type alias rather than a default value for `Map<A>`? +/// `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<dyn Any>; +impl<A: ?Sized + Downcast> Default for Map<A> { + #[inline] + fn default() -> Map<A> { + Map::new() + } +} + +impl<A: ?Sized + Downcast> Map<A> { + /// Create an empty collection. + #[inline] + pub fn new() -> Map<A> { + 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<T: IntoBox<A>>(&self) -> Option<&T> { + self.raw.get(&TypeId::of::<T>()).map(|any| unsafe { any.downcast_ref_unchecked::<T>() }) + } + + /// Gets the entry for the given type in the collection for in-place manipulation + #[inline] + pub fn entry<T: IntoBox<A>>(&mut self) -> Entry<'_, A, T> { + match self.raw.entry(TypeId::of::<T>()) { + 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<A>>, + type_: PhantomData<V>, +} + +/// 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<A>>, + type_: PhantomData<V>, +} + +/// 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<A>> 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<F: FnOnce() -> 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<A>> 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<A>> 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<T: Send>() {} + fn assert_sync<T: Sync>() {} + fn assert_debug<T: ::core::fmt::Debug>() {} + assert_send::<Map<dyn Any + Send>>(); + assert_send::<Map<dyn Any + Send + Sync>>(); + assert_sync::<Map<dyn Any + Send + Sync>>(); + assert_debug::<Map<dyn Any>>(); + assert_debug::<Map<dyn Any + Send>>(); + assert_debug::<Map<dyn Any + Send + Sync>>(); + assert_send::<Map<dyn CloneAny + Send>>(); + assert_send::<Map<dyn CloneAny + Send + Sync>>(); + assert_sync::<Map<dyn CloneAny + Send + Sync>>(); + assert_debug::<Map<dyn CloneAny>>(); + assert_debug::<Map<dyn CloneAny + Send>>(); + assert_debug::<Map<dyn CloneAny + Send + Sync>>(); + } + + #[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::<usize>()); + verify_hashing_with(TypeId::of::<()>()); + verify_hashing_with(TypeId::of::<str>()); + verify_hashing_with(TypeId::of::<&str>()); + verify_hashing_with(TypeId::of::<Vec<u8>>()); + } +} + +// impl some traits for dyn Any +use core::fmt; + +#[doc(hidden)] +pub trait CloneToAny { + /// Clone `self` into a new `Box<dyn CloneAny>` object. + fn clone_to_any(&self) -> Box<dyn CloneAny>; +} + +impl<T: Any + Clone> CloneToAny for T { + #[inline] + fn clone_to_any(&self) -> Box<dyn CloneAny> { + 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<dyn CloneAny> = (**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::<NotClone>() 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::<NotClone>() 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<T: 'static>(&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<T: 'static>(&mut self) -> &mut T; +} + +/// A trait for the conversion of an object into a boxed trait object. +pub trait IntoBox<A: ?Sized + Downcast>: Any { + /// Convert self into the appropriate boxed form. + fn into_box(self) -> Box<A>; +} + +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<T: 'static>(&self) -> &T { + &*(self as *const Self as *const T) + } + + #[inline] + unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T { + &mut *(self as *mut Self as *mut T) + } + } + + impl<T: $any_trait $(+ $auto_traits)*> IntoBox<dyn $any_trait $(+ $auto_traits)*> for T { + #[inline] + fn into_box(self) -> Box<dyn $any_trait $(+ $auto_traits)*> { + 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<T: Any + Clone> 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 24990d6a0e7..f26c7f6dfc2 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<String>), 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 1a9982fa8b2..d71e418c89b 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 e5aa3436518..bca0cbc36d1 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 5ee0c479284..dc92366d1c7 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -23,7 +23,7 @@ indexmap = "2.0.0" smol_str.workspace = true triomphe.workspace = true -rustc_lexer.workspace = true +rustc-dependencies.workspace = true parser.workspace = true profile.workspace = true @@ -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/src/ast/edit_in_place.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs index a150d9e6c07..a85e1d1d9d0 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 @@ -224,7 +224,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, @@ -433,7 +433,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 +462,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(()) } @@ -976,7 +980,9 @@ enum Foo { fn check_add_variant(before: &str, expected: &str, variant: ast::Variant) { let enum_ = ast_mut_from_text::<ast::Enum>(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/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index 17e311c0c50..31a858b91a7 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<Item = ast::Stmt>, tail_expr: Option<ast::Expr>, @@ -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} {{ }}")) } @@ -973,6 +976,11 @@ pub fn tuple_field(visibility: Option<ast::Visibility>, ty: ast::Type) -> ast::T ast_from_text(&format!("struct f({visibility}{ty});")) } +pub fn variant_list(variants: impl IntoIterator<Item = ast::Variant>) -> 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::FieldList>) -> ast::Variant { let field_list = match field_list { None => String::new(), @@ -1037,6 +1045,19 @@ pub fn struct_( ast_from_text(&format!("{visibility}struct {strukt_name}{type_params}{field_list}{semicolon}",)) } +pub fn enum_( + visibility: Option<ast::Visibility>, + 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}]")) } @@ -1149,6 +1170,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/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs index 87fd51d703c..8cc271d226c 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 27c8a13e58d..4939ab39049 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]: <https://github.com/rust-lang/rfcs/pull/2256> //! [Swift]: <https://github.com/apple/swift/blob/13d593df6f359d0cb2fc81cfaac273297c539455/lib/Syntax/README.md> +#![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<T> { green: GreenNode, - errors: Arc<Vec<SyntaxError>>, + errors: Arc<[SyntaxError]>, _ty: PhantomData<fn() -> T>, } @@ -86,7 +87,7 @@ impl<T> Clone for Parse<T> { impl<T> Parse<T> { fn new(green: GreenNode, errors: Vec<SyntaxError>) -> Parse<T> { - 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<T: AstNode> Parse<T> { T::cast(self.syntax_node()).unwrap() } - pub fn ok(self) -> Result<T, Arc<Vec<SyntaxError>>> { + pub fn ok(self) -> Result<T, Arc<[SyntaxError]>> { if self.errors.is_empty() { Ok(self.tree()) } else { @@ -143,7 +144,7 @@ impl Parse<SourceFile> { 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 1d4a89201ae..71762996cd7 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<N: AstNode> AstPtr<N> { Some(AstPtr { raw: self.raw, _ty: PhantomData }) } + pub fn kind(&self) -> parser::SyntaxKind { + self.raw.kind() + } + pub fn upcast<M: AstNode>(self) -> AstPtr<M> where N: Into<M>, @@ -84,6 +88,20 @@ impl<N: AstNode> AstPtr<N> { pub fn try_from_raw(raw: SyntaxNodePtr) -> Option<AstPtr<N>> { N::can_cast(raw.kind()).then_some(AstPtr { raw, _ty: PhantomData }) } + + pub fn wrap_left<R>(self) -> AstPtr<either::Either<N, R>> + where + either::Either<N, R>: AstNode, + { + AstPtr { raw: self.raw, _ty: PhantomData } + } + + pub fn wrap_right<L>(self) -> AstPtr<either::Either<L, N>> + where + either::Either<L, N>: AstNode, + { + AstPtr { raw: self.raw, _ty: PhantomData } + } } impl<N: AstNode> From<AstPtr<N>> 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 168439053c2..3010d77d827 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 dc6c96343d6..c2e921e4b6f 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<Vec<String>> { } fn lower_rule(acc: &mut Vec<Field>, 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<Field>, grammar: &Grammar, label: Option<&String>, r } // (T (',' T)* ','?) -fn lower_seperated_list( +fn lower_separated_list( acc: &mut Vec<Field>, 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 e0ec6a242ff..2b1bbac08e5 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/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index 573f56b003a..cc41d87f5d9 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -489,7 +489,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 +497,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 +507,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 +515,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 +863,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 +883,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 +996,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 +1012,7 @@ pub mod fmt { } impl<T: Debug> Debug for [T] { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { + fn fmt(&self, _f: &mut Formatter<'_>) -> Result { Ok(()) } } @@ -1062,7 +1062,7 @@ pub mod option { } } - pub fn and<U>(self, optb: Option<U>) -> Option<U> { + pub fn and<U>(self, _optb: Option<U>) -> Option<U> { loop {} } pub fn unwrap_or(self, default: T) -> T { @@ -1080,25 +1080,25 @@ pub mod option { } // endregion:result // region:fn - pub fn and_then<U, F>(self, f: F) -> Option<U> + pub fn and_then<U, F>(self, _f: F) -> Option<U> where F: FnOnce(T) -> Option<U>, { loop {} } - pub fn unwrap_or_else<F>(self, f: F) -> T + pub fn unwrap_or_else<F>(self, _f: F) -> T where F: FnOnce() -> T, { loop {} } - pub fn map_or<U, F>(self, default: U, f: F) -> U + pub fn map_or<U, F>(self, _default: U, _f: F) -> U where F: FnOnce(T) -> U, { loop {} } - pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U + pub fn map_or_else<U, D, F>(self, _default: D, _f: F) -> U where D: FnOnce() -> U, F: FnOnce(T) -> U, @@ -1129,7 +1129,7 @@ pub mod pin { pointer: P, } impl<P> Pin<P> { - pub fn new(pointer: P) -> Pin<P> { + pub fn new(_pointer: P) -> Pin<P> { loop {} } } @@ -1226,7 +1226,7 @@ pub mod iter { mod sources { mod repeat { - pub fn repeat<T>(elt: T) -> Repeat<T> { + pub fn repeat<T>(_elt: T) -> Repeat<T> { loop {} } @@ -1266,7 +1266,7 @@ pub mod iter { fn take(self, n: usize) -> crate::iter::Take<Self> { loop {} } - fn filter_map<B, F>(self, f: F) -> crate::iter::FilterMap<Self, F> + fn filter_map<B, F>(self, _f: F) -> crate::iter::FilterMap<Self, F> where Self: Sized, F: FnMut(Self::Item) -> Option<B>, @@ -1337,7 +1337,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/docs/dev/guide.md b/src/tools/rust-analyzer/docs/dev/guide.md index 56a68ef0437..a5f1811bf24 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/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index 71feed0f72c..7c76ae81bea 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`):: + -- @@ -744,6 +757,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 5dafd1a4c8c..b605de4c7b8 100644 --- a/src/tools/rust-analyzer/docs/user/manual.adoc +++ b/src/tools/rust-analyzer/docs/user/manual.adoc @@ -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. diff --git a/src/tools/rust-analyzer/editors/code/language-configuration.json b/src/tools/rust-analyzer/editors/code/language-configuration.json index 51f0e65f4fd..1c348b63f1a 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.json b/src/tools/rust-analyzer/editors/code/package.json index 233e7bf44b1..c7b877b2897 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": { @@ -249,6 +250,11 @@ "category": "rust-analyzer" }, { + "command": "rust-analyzer.openExternalDocs", + "title": "Open External Docs", + "category": "rust-analyzer" + }, + { "command": "rust-analyzer.openCargoToml", "title": "Open Cargo.toml", "category": "rust-analyzer" @@ -260,12 +266,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 +377,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 +486,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" }, @@ -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, @@ -1470,6 +1494,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 +1655,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 ba8546763ec..96e888402ba 100644 --- a/src/tools/rust-analyzer/editors/code/src/client.ts +++ b/src/tools/rust-analyzer/editors/code/src/client.ts @@ -389,6 +389,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 245557b1e88..7e24de664e9 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"; @@ -947,10 +948,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); - if (doclink != null) { - await vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(doclink)); + 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 }); + + 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 9821aee6f92..987d936943a 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<boolean>("showDependenciesExplorer"); } + + get statusBarClickAction() { + return this.get<string>("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 904efa4d5eb..84d1ad98bd9 100644 --- a/src/tools/rust-analyzer/editors/code/src/ctx.ts +++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts @@ -400,7 +400,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/lsp_ext.ts b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts index bb7896973f1..f959a76639e 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<lc.TextDocumentPositionParams, lc.Text export const openCargoToml = new lc.RequestType<OpenCargoTomlParams, lc.Location, void>( "experimental/openCargoToml", ); -export const openDocs = new lc.RequestType<lc.TextDocumentPositionParams, string | void, void>( +export interface DocsUrls { + local?: string; + web?: string; +} +export const openDocs = new lc.RequestType<lc.TextDocumentPositionParams, DocsUrls, void>( "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 ee5e5b1b80c..5de5aabc39f 100644 --- a/src/tools/rust-analyzer/editors/code/src/main.ts +++ b/src/tools/rust-analyzer/editors/code/src/main.ts @@ -170,6 +170,7 @@ function createCommands(): Record<string, CommandFactory> { 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/rust-bors.toml b/src/tools/rust-analyzer/rust-bors.toml new file mode 100644 index 00000000000..c31ba66c50f --- /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 f0cd3539975..95eed3ee172 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-installer/Cargo.toml b/src/tools/rust-installer/Cargo.toml index 471f2b5ac73..cdd867c5f15 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/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs index 16b8ce7a916..8a4089a56f0 100644 --- a/src/tools/rustfmt/src/closures.rs +++ b/src/tools/rustfmt/src/closures.rs @@ -264,7 +264,7 @@ fn rewrite_closure_fn_decl( "" }; let is_async = if asyncness.is_async() { "async " } else { "" }; - let mover = if capture == ast::CaptureBy::Value { + let mover = if matches!(capture, ast::CaptureBy::Value { .. }) { "move " } else { "" diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 8c2262fde81..fa941e6146a 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -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 { "" diff --git a/src/tools/suggest-tests/src/main.rs b/src/tools/suggest-tests/src/main.rs index 0b541b60cba..8e3625c2449 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/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 3a3b26c2f63..10215520227 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -107,7 +107,6 @@ const EXCEPTIONS_CARGO: ExceptionList = &[ // tidy-alphabetical-start ("bitmaps", "MPL-2.0+"), ("bytesize", "Apache-2.0"), - ("byteyarn", "Apache-2.0"), ("ciborium", "Apache-2.0"), ("ciborium-io", "Apache-2.0"), ("ciborium-ll", "Apache-2.0"), @@ -122,13 +121,13 @@ 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"), @@ -229,7 +228,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "ena", "equivalent", "errno", - "errno-dragonfly", "expect-test", "fallible-iterator", // dependency of `thorin` "fastrand", @@ -248,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", @@ -288,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", @@ -398,6 +400,32 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ // 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", + "zerovec-derive", + // tidy-alphabetical-end +]; + const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ // tidy-alphabetical-start "ahash", @@ -590,6 +618,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; } diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 11480e2be60..cb40c6e3a38 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 7e24793adee..dfa386b49de 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -10,7 +10,7 @@ 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 ISSUES_ENTRY_LIMIT: usize = 1852; const ROOT_ENTRY_LIMIT: usize = 867; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ diff --git a/src/version b/src/version index 7c7053aa238..32a6ce3c719 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.75.0 +1.76.0 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 00000000000..f3f08bf116a --- /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 00000000000..3670307ec81 --- /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 00000000000..963f087f22d --- /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 00000000000..e222a6dea38 --- /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 00000000000..73b1a520b06 --- /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 00000000000..4e7bc3e5154 --- /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/simd/unpadded-simd.rs b/tests/codegen/simd/unpadded-simd.rs index eb44dbd9313..797bca38ffa 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/unchecked_shifts.rs b/tests/codegen/unchecked_shifts.rs index aca9bec77df..eded894c6d0 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-reserve-extend.rs b/tests/codegen/vec-reserve-extend.rs new file mode 100644 index 00000000000..d95220104c2 --- /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<u8>) { + // 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 60d1352cd64..00000000000 --- 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 3cedb5ffbec..00000000000 --- 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 ed3f69bdc98..00000000000 --- 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/run-coverage-rustdoc/auxiliary/doctest_crate.rs b/tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs index c3210146d69..c3210146d69 100644 --- a/tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs +++ b/tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs diff --git a/tests/run-coverage-rustdoc/doctest.coverage b/tests/coverage-run-rustdoc/doctest.coverage index 5797784f411..5797784f411 100644 --- a/tests/run-coverage-rustdoc/doctest.coverage +++ b/tests/coverage-run-rustdoc/doctest.coverage diff --git a/tests/run-coverage-rustdoc/doctest.rs b/tests/coverage-run-rustdoc/doctest.rs index 4006d723ce0..4006d723ce0 100644 --- a/tests/run-coverage-rustdoc/doctest.rs +++ b/tests/coverage-run-rustdoc/doctest.rs diff --git a/tests/coverage/README.md b/tests/coverage/README.md new file mode 100644 index 00000000000..c72aa69c0ce --- /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 index 45d3795eff8..45d3795eff8 100644 --- a/tests/coverage-map/status-quo/abort.cov-map +++ b/tests/coverage/abort.cov-map diff --git a/tests/run-coverage/abort.coverage b/tests/coverage/abort.coverage index ceef6386780..ceef6386780 100644 --- a/tests/run-coverage/abort.coverage +++ b/tests/coverage/abort.coverage diff --git a/tests/coverage-map/status-quo/abort.rs b/tests/coverage/abort.rs index 98264bdc1af..98264bdc1af 100644 --- a/tests/coverage-map/status-quo/abort.rs +++ b/tests/coverage/abort.rs diff --git a/tests/coverage-map/status-quo/assert.cov-map b/tests/coverage/assert.cov-map index dd413123de7..dd413123de7 100644 --- a/tests/coverage-map/status-quo/assert.cov-map +++ b/tests/coverage/assert.cov-map diff --git a/tests/run-coverage/assert.coverage b/tests/coverage/assert.coverage index 8b997724c4a..8b997724c4a 100644 --- a/tests/run-coverage/assert.coverage +++ b/tests/coverage/assert.coverage diff --git a/tests/coverage-map/status-quo/assert.rs b/tests/coverage/assert.rs index 85e6662a6ad..85e6662a6ad 100644 --- a/tests/coverage-map/status-quo/assert.rs +++ b/tests/coverage/assert.rs diff --git a/tests/coverage-map/status-quo/async.cov-map b/tests/coverage/async.cov-map index 598791537ad..598791537ad 100644 --- a/tests/coverage-map/status-quo/async.cov-map +++ b/tests/coverage/async.cov-map diff --git a/tests/run-coverage/async.coverage b/tests/coverage/async.coverage index 07bc16c2d92..07bc16c2d92 100644 --- a/tests/run-coverage/async.coverage +++ b/tests/coverage/async.coverage diff --git a/tests/coverage-map/status-quo/async.rs b/tests/coverage/async.rs index efd9e62d64e..efd9e62d64e 100644 --- a/tests/coverage-map/status-quo/async.rs +++ b/tests/coverage/async.rs diff --git a/tests/coverage-map/status-quo/async2.cov-map b/tests/coverage/async2.cov-map index cc7aed9aee3..cc7aed9aee3 100644 --- a/tests/coverage-map/status-quo/async2.cov-map +++ b/tests/coverage/async2.cov-map diff --git a/tests/run-coverage/async2.coverage b/tests/coverage/async2.coverage index fcb0a3aed64..fcb0a3aed64 100644 --- a/tests/run-coverage/async2.coverage +++ b/tests/coverage/async2.coverage diff --git a/tests/coverage-map/status-quo/async2.rs b/tests/coverage/async2.rs index 2884ff297af..2884ff297af 100644 --- a/tests/coverage-map/status-quo/async2.rs +++ b/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 index 9dc50dae25a..9dc50dae25a 100644 --- a/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs +++ b/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 00000000000..6797c081d93 --- /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 index 88c5dac65cb..88c5dac65cb 100644 --- a/tests/run-coverage/auxiliary/unused_mod_helper.rs +++ b/tests/coverage/auxiliary/unused_mod_helper.rs diff --git a/tests/run-coverage/auxiliary/used_crate.rs b/tests/coverage/auxiliary/used_crate.rs index c086ef21e1a..c086ef21e1a 100644 --- a/tests/run-coverage/auxiliary/used_crate.rs +++ b/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 index e8929de6b36..e8929de6b36 100644 --- a/tests/run-coverage/auxiliary/used_inline_crate.rs +++ b/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 index 0b8081acfa6..0b8081acfa6 100644 --- a/tests/coverage-map/status-quo/bad_counter_ids.cov-map +++ b/tests/coverage/bad_counter_ids.cov-map diff --git a/tests/run-coverage/bad_counter_ids.coverage b/tests/coverage/bad_counter_ids.coverage index d69ebf160ea..d69ebf160ea 100644 --- a/tests/run-coverage/bad_counter_ids.coverage +++ b/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 index ef5460102b7..ef5460102b7 100644 --- a/tests/coverage-map/status-quo/bad_counter_ids.rs +++ b/tests/coverage/bad_counter_ids.rs diff --git a/tests/coverage-map/status-quo/closure.cov-map b/tests/coverage/closure.cov-map index 522c1e73afe..522c1e73afe 100644 --- a/tests/coverage-map/status-quo/closure.cov-map +++ b/tests/coverage/closure.cov-map diff --git a/tests/run-coverage/closure.coverage b/tests/coverage/closure.coverage index 67014f792c8..67014f792c8 100644 --- a/tests/run-coverage/closure.coverage +++ b/tests/coverage/closure.coverage diff --git a/tests/coverage-map/status-quo/closure.rs b/tests/coverage/closure.rs index 16a2c4e33bd..16a2c4e33bd 100644 --- a/tests/coverage-map/status-quo/closure.rs +++ b/tests/coverage/closure.rs diff --git a/tests/coverage-map/status-quo/closure_bug.cov-map b/tests/coverage/closure_bug.cov-map index 90eeb1a6686..90eeb1a6686 100644 --- a/tests/coverage-map/status-quo/closure_bug.cov-map +++ b/tests/coverage/closure_bug.cov-map diff --git a/tests/run-coverage/closure_bug.coverage b/tests/coverage/closure_bug.coverage index f3299834bce..f3299834bce 100644 --- a/tests/run-coverage/closure_bug.coverage +++ b/tests/coverage/closure_bug.coverage diff --git a/tests/coverage-map/status-quo/closure_bug.rs b/tests/coverage/closure_bug.rs index 739bc5f0b51..739bc5f0b51 100644 --- a/tests/coverage-map/status-quo/closure_bug.rs +++ b/tests/coverage/closure_bug.rs diff --git a/tests/coverage-map/status-quo/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index b02c7e2e4c6..b02c7e2e4c6 100644 --- a/tests/coverage-map/status-quo/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map diff --git a/tests/run-coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage index 0f2c917e090..0f2c917e090 100644 --- a/tests/run-coverage/closure_macro.coverage +++ b/tests/coverage/closure_macro.coverage diff --git a/tests/coverage-map/status-quo/closure_macro.rs b/tests/coverage/closure_macro.rs index 9b289141c2e..9b289141c2e 100644 --- a/tests/coverage-map/status-quo/closure_macro.rs +++ b/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 index 7f8666948d9..7f8666948d9 100644 --- a/tests/coverage-map/status-quo/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map diff --git a/tests/run-coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage index 74247f1bc6f..74247f1bc6f 100644 --- a/tests/run-coverage/closure_macro_async.coverage +++ b/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 index b4275599e59..b4275599e59 100644 --- a/tests/coverage-map/status-quo/closure_macro_async.rs +++ b/tests/coverage/closure_macro_async.rs diff --git a/tests/coverage-map/status-quo/conditions.cov-map b/tests/coverage/conditions.cov-map index 7600d2d96bd..7600d2d96bd 100644 --- a/tests/coverage-map/status-quo/conditions.cov-map +++ b/tests/coverage/conditions.cov-map diff --git a/tests/run-coverage/conditions.coverage b/tests/coverage/conditions.coverage index 473335ff641..473335ff641 100644 --- a/tests/run-coverage/conditions.coverage +++ b/tests/coverage/conditions.coverage diff --git a/tests/coverage-map/status-quo/conditions.rs b/tests/coverage/conditions.rs index fa7f2a116c2..fa7f2a116c2 100644 --- a/tests/coverage-map/status-quo/conditions.rs +++ b/tests/coverage/conditions.rs diff --git a/tests/coverage-map/status-quo/continue.cov-map b/tests/coverage/continue.cov-map index 82f3d7c6095..82f3d7c6095 100644 --- a/tests/coverage-map/status-quo/continue.cov-map +++ b/tests/coverage/continue.cov-map diff --git a/tests/run-coverage/continue.coverage b/tests/coverage/continue.coverage index 4916cac0038..4916cac0038 100644 --- a/tests/run-coverage/continue.coverage +++ b/tests/coverage/continue.coverage diff --git a/tests/coverage-map/status-quo/continue.rs b/tests/coverage/continue.rs index 624aa98341b..624aa98341b 100644 --- a/tests/coverage-map/status-quo/continue.rs +++ b/tests/coverage/continue.rs diff --git a/tests/coverage-map/status-quo/coroutine.cov-map b/tests/coverage/coroutine.cov-map index 2f4936d9ab8..2f4936d9ab8 100644 --- a/tests/coverage-map/status-quo/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map diff --git a/tests/run-coverage/coroutine.coverage b/tests/coverage/coroutine.coverage index 3a9791a0dbd..3a9791a0dbd 100644 --- a/tests/run-coverage/coroutine.coverage +++ b/tests/coverage/coroutine.coverage diff --git a/tests/coverage-map/status-quo/coroutine.rs b/tests/coverage/coroutine.rs index 86d19af6f4f..86d19af6f4f 100644 --- a/tests/coverage-map/status-quo/coroutine.rs +++ b/tests/coverage/coroutine.rs diff --git a/tests/coverage-map/status-quo/dead_code.cov-map b/tests/coverage/dead_code.cov-map index 0b8a40a8cde..0b8a40a8cde 100644 --- a/tests/coverage-map/status-quo/dead_code.cov-map +++ b/tests/coverage/dead_code.cov-map diff --git a/tests/run-coverage/dead_code.coverage b/tests/coverage/dead_code.coverage index c4ee9f23f08..c4ee9f23f08 100644 --- a/tests/run-coverage/dead_code.coverage +++ b/tests/coverage/dead_code.coverage diff --git a/tests/coverage-map/status-quo/dead_code.rs b/tests/coverage/dead_code.rs index 3492712a6f9..3492712a6f9 100644 --- a/tests/coverage-map/status-quo/dead_code.rs +++ b/tests/coverage/dead_code.rs diff --git a/tests/coverage-map/status-quo/drop_trait.cov-map b/tests/coverage/drop_trait.cov-map index 203d1048b05..203d1048b05 100644 --- a/tests/coverage-map/status-quo/drop_trait.cov-map +++ b/tests/coverage/drop_trait.cov-map diff --git a/tests/run-coverage/drop_trait.coverage b/tests/coverage/drop_trait.coverage index 2c9439a93b1..2c9439a93b1 100644 --- a/tests/run-coverage/drop_trait.coverage +++ b/tests/coverage/drop_trait.coverage diff --git a/tests/coverage-map/status-quo/drop_trait.rs b/tests/coverage/drop_trait.rs index 7b062719c6b..7b062719c6b 100644 --- a/tests/coverage-map/status-quo/drop_trait.rs +++ b/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 index 6e26c61aac9..6e26c61aac9 100644 --- a/tests/coverage-map/fn_sig_into_try.cov-map +++ b/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 index f1ddb1da780..f1ddb1da780 100644 --- a/tests/run-coverage/fn_sig_into_try.coverage +++ b/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 index 92850c8a188..92850c8a188 100644 --- a/tests/coverage-map/fn_sig_into_try.rs +++ b/tests/coverage/fn_sig_into_try.rs diff --git a/tests/coverage-map/status-quo/generics.cov-map b/tests/coverage/generics.cov-map index 6079a433cd0..6079a433cd0 100644 --- a/tests/coverage-map/status-quo/generics.cov-map +++ b/tests/coverage/generics.cov-map diff --git a/tests/run-coverage/generics.coverage b/tests/coverage/generics.coverage index 09839183566..09839183566 100644 --- a/tests/run-coverage/generics.coverage +++ b/tests/coverage/generics.coverage diff --git a/tests/coverage-map/status-quo/generics.rs b/tests/coverage/generics.rs index bf4c2d8d685..bf4c2d8d685 100644 --- a/tests/coverage-map/status-quo/generics.rs +++ b/tests/coverage/generics.rs diff --git a/tests/coverage-map/status-quo/if.cov-map b/tests/coverage/if.cov-map index 391a69e0e82..391a69e0e82 100644 --- a/tests/coverage-map/status-quo/if.cov-map +++ b/tests/coverage/if.cov-map diff --git a/tests/run-coverage/if.coverage b/tests/coverage/if.coverage index 2e6845190aa..2e6845190aa 100644 --- a/tests/run-coverage/if.coverage +++ b/tests/coverage/if.coverage diff --git a/tests/coverage-map/status-quo/if.rs b/tests/coverage/if.rs index 8ad5042ff7b..8ad5042ff7b 100644 --- a/tests/coverage-map/status-quo/if.rs +++ b/tests/coverage/if.rs diff --git a/tests/coverage-map/status-quo/if_else.cov-map b/tests/coverage/if_else.cov-map index da692ca3aa2..da692ca3aa2 100644 --- a/tests/coverage-map/status-quo/if_else.cov-map +++ b/tests/coverage/if_else.cov-map diff --git a/tests/run-coverage/if_else.coverage b/tests/coverage/if_else.coverage index 0274401f004..0274401f004 100644 --- a/tests/run-coverage/if_else.coverage +++ b/tests/coverage/if_else.coverage diff --git a/tests/coverage-map/status-quo/if_else.rs b/tests/coverage/if_else.rs index 3244e1e3afd..3244e1e3afd 100644 --- a/tests/coverage-map/status-quo/if_else.rs +++ b/tests/coverage/if_else.rs diff --git a/tests/coverage-map/status-quo/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index 958b423f24c..958b423f24c 100644 --- a/tests/coverage-map/status-quo/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map diff --git a/tests/run-coverage/inline-dead.coverage b/tests/coverage/inline-dead.coverage index de96aa17acd..de96aa17acd 100644 --- a/tests/run-coverage/inline-dead.coverage +++ b/tests/coverage/inline-dead.coverage diff --git a/tests/coverage-map/status-quo/inline-dead.rs b/tests/coverage/inline-dead.rs index 854fa062967..854fa062967 100644 --- a/tests/coverage-map/status-quo/inline-dead.rs +++ b/tests/coverage/inline-dead.rs diff --git a/tests/coverage-map/status-quo/inline.cov-map b/tests/coverage/inline.cov-map index 72b10fd0cc2..72b10fd0cc2 100644 --- a/tests/coverage-map/status-quo/inline.cov-map +++ b/tests/coverage/inline.cov-map diff --git a/tests/run-coverage/inline.coverage b/tests/coverage/inline.coverage index 6efd9a0830b..6efd9a0830b 100644 --- a/tests/run-coverage/inline.coverage +++ b/tests/coverage/inline.coverage diff --git a/tests/coverage-map/status-quo/inline.rs b/tests/coverage/inline.rs index 9cfab9ddbad..9cfab9ddbad 100644 --- a/tests/coverage-map/status-quo/inline.rs +++ b/tests/coverage/inline.rs diff --git a/tests/coverage-map/status-quo/inner_items.cov-map b/tests/coverage/inner_items.cov-map index 3f39d74efba..3f39d74efba 100644 --- a/tests/coverage-map/status-quo/inner_items.cov-map +++ b/tests/coverage/inner_items.cov-map diff --git a/tests/run-coverage/inner_items.coverage b/tests/coverage/inner_items.coverage index 65493bcd9db..65493bcd9db 100644 --- a/tests/run-coverage/inner_items.coverage +++ b/tests/coverage/inner_items.coverage diff --git a/tests/coverage-map/status-quo/inner_items.rs b/tests/coverage/inner_items.rs index bcb62b3031c..bcb62b3031c 100644 --- a/tests/coverage-map/status-quo/inner_items.rs +++ b/tests/coverage/inner_items.rs diff --git a/tests/coverage-map/status-quo/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map index f5db3a89750..f5db3a89750 100644 --- a/tests/coverage-map/status-quo/issue-83601.cov-map +++ b/tests/coverage/issue-83601.cov-map diff --git a/tests/run-coverage/issue-83601.coverage b/tests/coverage/issue-83601.coverage index 7995332cad3..7995332cad3 100644 --- a/tests/run-coverage/issue-83601.coverage +++ b/tests/coverage/issue-83601.coverage diff --git a/tests/coverage-map/status-quo/issue-83601.rs b/tests/coverage/issue-83601.rs index 0b72a81947c..0b72a81947c 100644 --- a/tests/coverage-map/status-quo/issue-83601.rs +++ b/tests/coverage/issue-83601.rs diff --git a/tests/coverage-map/status-quo/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index 82582b309bf..82582b309bf 100644 --- a/tests/coverage-map/status-quo/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map diff --git a/tests/run-coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage index e693866e277..e693866e277 100644 --- a/tests/run-coverage/issue-84561.coverage +++ b/tests/coverage/issue-84561.coverage diff --git a/tests/coverage-map/status-quo/issue-84561.rs b/tests/coverage/issue-84561.rs index facf5b5b4cf..facf5b5b4cf 100644 --- a/tests/coverage-map/status-quo/issue-84561.rs +++ b/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 00000000000..d1c449b9a35 --- /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 index cbc910664d0..cbc910664d0 100644 --- a/tests/run-coverage/issue-85461.coverage +++ b/tests/coverage/issue-85461.coverage diff --git a/tests/run-coverage/issue-85461.rs b/tests/coverage/issue-85461.rs index 9d4c90a827e..9d4c90a827e 100644 --- a/tests/run-coverage/issue-85461.rs +++ b/tests/coverage/issue-85461.rs diff --git a/tests/coverage-map/status-quo/issue-93054.cov-map b/tests/coverage/issue-93054.cov-map index c2c6e9a6516..c2c6e9a6516 100644 --- a/tests/coverage-map/status-quo/issue-93054.cov-map +++ b/tests/coverage/issue-93054.cov-map diff --git a/tests/run-coverage/issue-93054.coverage b/tests/coverage/issue-93054.coverage index 15f225326a4..15f225326a4 100644 --- a/tests/run-coverage/issue-93054.coverage +++ b/tests/coverage/issue-93054.coverage diff --git a/tests/coverage-map/status-quo/issue-93054.rs b/tests/coverage/issue-93054.rs index da546cfeef8..da546cfeef8 100644 --- a/tests/coverage-map/status-quo/issue-93054.rs +++ b/tests/coverage/issue-93054.rs diff --git a/tests/coverage-map/status-quo/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map index 0ad393c40fa..0ad393c40fa 100644 --- a/tests/coverage-map/status-quo/lazy_boolean.cov-map +++ b/tests/coverage/lazy_boolean.cov-map diff --git a/tests/run-coverage/lazy_boolean.coverage b/tests/coverage/lazy_boolean.coverage index 8f14082ef68..8f14082ef68 100644 --- a/tests/run-coverage/lazy_boolean.coverage +++ b/tests/coverage/lazy_boolean.coverage diff --git a/tests/coverage-map/status-quo/lazy_boolean.rs b/tests/coverage/lazy_boolean.rs index bb6219e851c..bb6219e851c 100644 --- a/tests/coverage-map/status-quo/lazy_boolean.rs +++ b/tests/coverage/lazy_boolean.rs diff --git a/tests/coverage-map/long_and_wide.cov-map b/tests/coverage/long_and_wide.cov-map index 97aebf9b18a..97aebf9b18a 100644 --- a/tests/coverage-map/long_and_wide.cov-map +++ b/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 00000000000..d7d29ca40cd --- /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 index a7cbcd48027..a7cbcd48027 100644 --- a/tests/coverage-map/long_and_wide.rs +++ b/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 index 75018442d07..75018442d07 100644 --- a/tests/coverage-map/status-quo/loop_break_value.cov-map +++ b/tests/coverage/loop_break_value.cov-map diff --git a/tests/run-coverage/loop_break_value.coverage b/tests/coverage/loop_break_value.coverage index 1f0630636dd..1f0630636dd 100644 --- a/tests/run-coverage/loop_break_value.coverage +++ b/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 index dbc4fad7a23..dbc4fad7a23 100644 --- a/tests/coverage-map/status-quo/loop_break_value.rs +++ b/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 index 813583a9de7..813583a9de7 100644 --- a/tests/coverage-map/status-quo/loops_branches.cov-map +++ b/tests/coverage/loops_branches.cov-map diff --git a/tests/run-coverage/loops_branches.coverage b/tests/coverage/loops_branches.coverage index 8cd6f1be3f7..8cd6f1be3f7 100644 --- a/tests/run-coverage/loops_branches.coverage +++ b/tests/coverage/loops_branches.coverage diff --git a/tests/coverage-map/status-quo/loops_branches.rs b/tests/coverage/loops_branches.rs index f3a343bcc1f..f3a343bcc1f 100644 --- a/tests/coverage-map/status-quo/loops_branches.rs +++ b/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 00000000000..b84628fc788 --- /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 00000000000..cadf7024657 --- /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 <https://github.com/rust-lang/rust/issues/117788>. + 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 00000000000..5d15977c498 --- /dev/null +++ b/tests/coverage/macro_name_span.rs @@ -0,0 +1,25 @@ +// edition: 2021 + +// Regression test for <https://github.com/rust-lang/rust/issues/117788>. +// 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 index d63407a99c3..d63407a99c3 100644 --- a/tests/coverage-map/status-quo/match_or_pattern.cov-map +++ b/tests/coverage/match_or_pattern.cov-map diff --git a/tests/run-coverage/match_or_pattern.coverage b/tests/coverage/match_or_pattern.coverage index 94c7967215c..94c7967215c 100644 --- a/tests/run-coverage/match_or_pattern.coverage +++ b/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 index ab7aee51d1b..ab7aee51d1b 100644 --- a/tests/coverage-map/status-quo/match_or_pattern.rs +++ b/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 index 35d92594e75..35d92594e75 100644 --- a/tests/coverage-map/status-quo/nested_loops.cov-map +++ b/tests/coverage/nested_loops.cov-map diff --git a/tests/run-coverage/nested_loops.coverage b/tests/coverage/nested_loops.coverage index 143d0d26aa7..143d0d26aa7 100644 --- a/tests/run-coverage/nested_loops.coverage +++ b/tests/coverage/nested_loops.coverage diff --git a/tests/coverage-map/status-quo/nested_loops.rs b/tests/coverage/nested_loops.rs index 4c7c7842796..4c7c7842796 100644 --- a/tests/coverage-map/status-quo/nested_loops.rs +++ b/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 index 05b6448bbd2..05b6448bbd2 100644 --- a/tests/coverage-map/status-quo/no_cov_crate.cov-map +++ b/tests/coverage/no_cov_crate.cov-map diff --git a/tests/run-coverage/no_cov_crate.coverage b/tests/coverage/no_cov_crate.coverage index f5a0322bf3e..f5a0322bf3e 100644 --- a/tests/run-coverage/no_cov_crate.coverage +++ b/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 index e12e4bc55e3..e12e4bc55e3 100644 --- a/tests/coverage-map/status-quo/no_cov_crate.rs +++ b/tests/coverage/no_cov_crate.rs diff --git a/tests/coverage-map/status-quo/overflow.cov-map b/tests/coverage/overflow.cov-map index bfffd9b2ab5..39a5c05f879 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 index cee076e88cd..4f8dffc0c48 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 index bbb65c1b35d..1c40771b274 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 index f6089ce55ae..f6089ce55ae 100644 --- a/tests/coverage-map/status-quo/panic_unwind.cov-map +++ b/tests/coverage/panic_unwind.cov-map diff --git a/tests/run-coverage/panic_unwind.coverage b/tests/coverage/panic_unwind.coverage index 2b0777ef215..2b0777ef215 100644 --- a/tests/run-coverage/panic_unwind.coverage +++ b/tests/coverage/panic_unwind.coverage diff --git a/tests/coverage-map/status-quo/panic_unwind.rs b/tests/coverage/panic_unwind.rs index 638d2eb6aaa..638d2eb6aaa 100644 --- a/tests/coverage-map/status-quo/panic_unwind.rs +++ b/tests/coverage/panic_unwind.rs diff --git a/tests/coverage-map/status-quo/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map index 3549116db7a..3549116db7a 100644 --- a/tests/coverage-map/status-quo/partial_eq.cov-map +++ b/tests/coverage/partial_eq.cov-map diff --git a/tests/run-coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage index c6d9ad6cf27..c6d9ad6cf27 100644 --- a/tests/run-coverage/partial_eq.coverage +++ b/tests/coverage/partial_eq.coverage diff --git a/tests/coverage-map/status-quo/partial_eq.rs b/tests/coverage/partial_eq.rs index dd8b42c18ce..dd8b42c18ce 100644 --- a/tests/coverage-map/status-quo/partial_eq.rs +++ b/tests/coverage/partial_eq.rs diff --git a/tests/coverage-map/status-quo/simple_loop.cov-map b/tests/coverage/simple_loop.cov-map index f1691ffc5e6..f1691ffc5e6 100644 --- a/tests/coverage-map/status-quo/simple_loop.cov-map +++ b/tests/coverage/simple_loop.cov-map diff --git a/tests/run-coverage/simple_loop.coverage b/tests/coverage/simple_loop.coverage index 691c6cd1e7d..691c6cd1e7d 100644 --- a/tests/run-coverage/simple_loop.coverage +++ b/tests/coverage/simple_loop.coverage diff --git a/tests/coverage-map/status-quo/simple_loop.rs b/tests/coverage/simple_loop.rs index 6f7f23475b8..6f7f23475b8 100644 --- a/tests/coverage-map/status-quo/simple_loop.rs +++ b/tests/coverage/simple_loop.rs diff --git a/tests/coverage-map/status-quo/simple_match.cov-map b/tests/coverage/simple_match.cov-map index 4a32745d292..4a32745d292 100644 --- a/tests/coverage-map/status-quo/simple_match.cov-map +++ b/tests/coverage/simple_match.cov-map diff --git a/tests/run-coverage/simple_match.coverage b/tests/coverage/simple_match.coverage index 7f5dd3bb646..7f5dd3bb646 100644 --- a/tests/run-coverage/simple_match.coverage +++ b/tests/coverage/simple_match.coverage diff --git a/tests/coverage-map/status-quo/simple_match.rs b/tests/coverage/simple_match.rs index be99e59a826..be99e59a826 100644 --- a/tests/coverage-map/status-quo/simple_match.rs +++ b/tests/coverage/simple_match.rs diff --git a/tests/coverage-map/status-quo/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map index db027f3dc32..3cbda6fbe1a 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::<char> +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::<i32> 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 index 8733bf48a9c..c70d7b3b282 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::<char>(cond); LL| 1| } LL| 1| generic_fn::<i32>(cond); diff --git a/tests/coverage-map/status-quo/sort_groups.rs b/tests/coverage/sort_groups.rs index f89f9f3ec61..5adbbc6a87d 100644 --- a/tests/coverage-map/status-quo/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::<char>(cond); } generic_fn::<i32>(cond); diff --git a/tests/coverage-map/status-quo/test_harness.cov-map b/tests/coverage/test_harness.cov-map index 6940d2e2824..6940d2e2824 100644 --- a/tests/coverage-map/status-quo/test_harness.cov-map +++ b/tests/coverage/test_harness.cov-map diff --git a/tests/run-coverage/test_harness.coverage b/tests/coverage/test_harness.coverage index ff6009f6fce..ff6009f6fce 100644 --- a/tests/run-coverage/test_harness.coverage +++ b/tests/coverage/test_harness.coverage diff --git a/tests/coverage-map/status-quo/test_harness.rs b/tests/coverage/test_harness.rs index 12a755734c1..12a755734c1 100644 --- a/tests/coverage-map/status-quo/test_harness.rs +++ b/tests/coverage/test_harness.rs diff --git a/tests/coverage-map/status-quo/tight_inf_loop.cov-map b/tests/coverage/tight_inf_loop.cov-map index 7fe3146b080..7fe3146b080 100644 --- a/tests/coverage-map/status-quo/tight_inf_loop.cov-map +++ b/tests/coverage/tight_inf_loop.cov-map diff --git a/tests/run-coverage/tight_inf_loop.coverage b/tests/coverage/tight_inf_loop.coverage index c15c76b3aba..c15c76b3aba 100644 --- a/tests/run-coverage/tight_inf_loop.coverage +++ b/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 index cef99027aaa..cef99027aaa 100644 --- a/tests/coverage-map/status-quo/tight_inf_loop.rs +++ b/tests/coverage/tight_inf_loop.rs diff --git a/tests/coverage-map/trivial.cov-map b/tests/coverage/trivial.cov-map index 874e294a1c4..874e294a1c4 100644 --- a/tests/coverage-map/trivial.cov-map +++ b/tests/coverage/trivial.cov-map diff --git a/tests/coverage/trivial.coverage b/tests/coverage/trivial.coverage new file mode 100644 index 00000000000..4f417979ef9 --- /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 index d0a9b44fb36..d0a9b44fb36 100644 --- a/tests/coverage-map/trivial.rs +++ b/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 index 8367103a21a..8367103a21a 100644 --- a/tests/coverage-map/status-quo/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map diff --git a/tests/run-coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage index 5d48cbd62f2..5d48cbd62f2 100644 --- a/tests/run-coverage/try_error_result.coverage +++ b/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 index 557cbf22bfa..557cbf22bfa 100644 --- a/tests/coverage-map/status-quo/try_error_result.rs +++ b/tests/coverage/try_error_result.rs diff --git a/tests/coverage-map/unreachable.cov-map b/tests/coverage/unreachable.cov-map index 495419820c1..495419820c1 100644 --- a/tests/coverage-map/unreachable.cov-map +++ b/tests/coverage/unreachable.cov-map diff --git a/tests/run-coverage/unreachable.coverage b/tests/coverage/unreachable.coverage index fa0ac9ccfa1..fa0ac9ccfa1 100644 --- a/tests/run-coverage/unreachable.coverage +++ b/tests/coverage/unreachable.coverage diff --git a/tests/coverage-map/unreachable.rs b/tests/coverage/unreachable.rs index 6385bfa160d..6385bfa160d 100644 --- a/tests/coverage-map/unreachable.rs +++ b/tests/coverage/unreachable.rs diff --git a/tests/coverage-map/status-quo/unused.cov-map b/tests/coverage/unused.cov-map index 9383d1e90ac..9383d1e90ac 100644 --- a/tests/coverage-map/status-quo/unused.cov-map +++ b/tests/coverage/unused.cov-map diff --git a/tests/run-coverage/unused.coverage b/tests/coverage/unused.coverage index 056ffeb021a..056ffeb021a 100644 --- a/tests/run-coverage/unused.coverage +++ b/tests/coverage/unused.coverage diff --git a/tests/coverage-map/status-quo/unused.rs b/tests/coverage/unused.rs index d985af13547..d985af13547 100644 --- a/tests/coverage-map/status-quo/unused.rs +++ b/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 00000000000..241cb2610ff --- /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 index a8fa24ac6a7..a8fa24ac6a7 100644 --- a/tests/run-coverage/unused_mod.coverage +++ b/tests/coverage/unused_mod.coverage diff --git a/tests/run-coverage/unused_mod.rs b/tests/coverage/unused_mod.rs index 6e62839c998..6e62839c998 100644 --- a/tests/run-coverage/unused_mod.rs +++ b/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 00000000000..9c06eab7005 --- /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::<alloc::vec::Vec<i32>> +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<i32>> +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 index 50d92102a10..50d92102a10 100644 --- a/tests/run-coverage/uses_crate.coverage +++ b/tests/coverage/uses_crate.coverage diff --git a/tests/run-coverage/uses_crate.rs b/tests/coverage/uses_crate.rs index ab203ad781d..ab203ad781d 100644 --- a/tests/run-coverage/uses_crate.rs +++ b/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 00000000000..6b621825c88 --- /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::<alloc::vec::Vec<i32>> +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<i32>> +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 index cc0e01ffde1..cc0e01ffde1 100644 --- a/tests/run-coverage/uses_inline_crate.coverage +++ b/tests/coverage/uses_inline_crate.coverage diff --git a/tests/run-coverage/uses_inline_crate.rs b/tests/coverage/uses_inline_crate.rs index d7b4c3c057f..d7b4c3c057f 100644 --- a/tests/run-coverage/uses_inline_crate.rs +++ b/tests/coverage/uses_inline_crate.rs diff --git a/tests/coverage-map/status-quo/while.cov-map b/tests/coverage/while.cov-map index af250f3fb71..af250f3fb71 100644 --- a/tests/coverage-map/status-quo/while.cov-map +++ b/tests/coverage/while.cov-map diff --git a/tests/run-coverage/while.coverage b/tests/coverage/while.coverage index c9d497651c9..c9d497651c9 100644 --- a/tests/run-coverage/while.coverage +++ b/tests/coverage/while.coverage diff --git a/tests/coverage-map/status-quo/while.rs b/tests/coverage/while.rs index 781b90b3566..781b90b3566 100644 --- a/tests/coverage-map/status-quo/while.rs +++ b/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 index 369ebe891f1..369ebe891f1 100644 --- a/tests/coverage-map/status-quo/while_early_ret.cov-map +++ b/tests/coverage/while_early_ret.cov-map diff --git a/tests/run-coverage/while_early_ret.coverage b/tests/coverage/while_early_ret.coverage index 49d39d36603..49d39d36603 100644 --- a/tests/run-coverage/while_early_ret.coverage +++ b/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 index b2f0eee2cc0..b2f0eee2cc0 100644 --- a/tests/coverage-map/status-quo/while_early_ret.rs +++ b/tests/coverage/while_early_ret.rs diff --git a/tests/coverage-map/status-quo/yield.cov-map b/tests/coverage/yield.cov-map index c9c9709fa4f..c9c9709fa4f 100644 --- a/tests/coverage-map/status-quo/yield.cov-map +++ b/tests/coverage/yield.cov-map diff --git a/tests/run-coverage/yield.coverage b/tests/coverage/yield.coverage index d7e455f211e..d7e455f211e 100644 --- a/tests/run-coverage/yield.coverage +++ b/tests/coverage/yield.coverage diff --git a/tests/coverage-map/status-quo/yield.rs b/tests/coverage/yield.rs index b7e2ba31b59..b7e2ba31b59 100644 --- a/tests/coverage-map/status-quo/yield.rs +++ b/tests/coverage/yield.rs diff --git a/tests/debuginfo/simple-struct.rs b/tests/debuginfo/simple-struct.rs index aa3cf023a71..fea8109223a 100644 --- a/tests/debuginfo/simple-struct.rs +++ b/tests/debuginfo/simple-struct.rs @@ -1,7 +1,7 @@ // min-lldb-version: 310 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 -// compile-flags:-g +// compile-flags: -g -Zmir-enable-passes=-CheckAlignment // === GDB TESTS =================================================================================== 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 396e4a378f6..111dd8e97f9 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 9e442e0f98a..a83a6c07461 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) -> 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 00000000000..e3c4ffac358 --- /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 00000000000..efdf2ddb1d0 --- /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 1946c70e476..b99b0b99559 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 b6175b05156..d1d86b55d68 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 0b57d1b97e1..1d4fe67f350 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 00000000000..b06c1639c3f --- /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 00000000000..26c82edf2d5 --- /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 00000000000..1bb72074846 --- /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_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index f5d822520a7..87c07279552 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<u16>; + debug f => _10; + let _11: std::option::Option<u16>; scope 7 { -- debug o => _6; -+ debug o => const Option::<u16>::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::<u16>::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::<u16>::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 d8ae08a0723..0e5ac4b8bd6 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 index 4eafb8d0917..4eafb8d0917 100644 --- a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff +++ b/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 index 445d9895d6a..445d9895d6a 100644 --- a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff +++ b/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 00000000000..ec9da6e8e5c --- /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/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs index 8a5289d5899..2571c3856f4 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_miscompile.rs b/tests/mir-opt/const_prop_miscompile.rs deleted file mode 100644 index 00696535ac1..00000000000 --- 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 c6b8ad3571f..a44e65164af 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 2970f5f0b8d..bc6760707cc 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 2077874ee9a..8593d9fa9ab 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 8629d535bcf..438a90dddd0 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/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs index dcd15fb2b09..b2eb64756f9 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 8896f5ff345..c9ad06a9da2 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 10a66ced026..6e082acdbd3 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/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 2989582d038..b4bd45ba597 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 2989582d038..b4bd45ba597 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 90ec3ab49ad..ebb2f70a475 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/reference_prop.rs b/tests/mir-opt/reference_prop.rs index 36134e019ad..1b9c8fe15c2 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 61329bb75d1..54da6ee659f 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 61329bb75d1..54da6ee659f 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/while_storage.rs b/tests/mir-opt/while_storage.rs deleted file mode 100644 index 3a3d451ee8d..00000000000 --- 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 21c4b92cf04..00000000000 --- 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 21c4b92cf04..00000000000 --- 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 98264bdc1af..00000000000 --- 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 85e6662a6ad..00000000000 --- 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 efd9e62d64e..00000000000 --- 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<F: Future>(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 2884ff297af..00000000000 --- 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<F: Future>(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 ef5460102b7..00000000000 --- 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 <https://github.com/rust-lang/rust/issues/117012>. -// -// 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 16a2c4e33bd..00000000000 --- 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 -// <https://github.com/rust-lang/rust/pull/83666>. - -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::<Vec<_>>() - ); - - 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 739bc5f0b51..00000000000 --- 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 9b289141c2e..00000000000 --- 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<String, String> { - 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 b4275599e59..00000000000 --- 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<String, String> { - 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<F: Future>(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 fa7f2a116c2..00000000000 --- 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 624aa98341b..00000000000 --- 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 86d19af6f4f..00000000000 --- 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<u32, String> { - 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 3492712a6f9..00000000000 --- 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 7b062719c6b..00000000000 --- 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 92850c8a188..00000000000 --- 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<i32> -{ - Some(7i32); - Some(0) -} - -fn b() -> Option<i32> -{ - Some(7i32)?; - Some(0) -} - -fn c() -> Option<i32> -{ - let _ = Some(7i32)?; - Some(0) -} - -fn d() -> Option<i32> -{ - 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 bf4c2d8d685..00000000000 --- a/tests/run-coverage/generics.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 1 - -struct Firework<T> where T: Copy + std::fmt::Display { - strength: T, -} - -impl<T> Firework<T> where T: Copy + std::fmt::Display { - #[inline(always)] - fn set_strength(&mut self, new_strength: T) { - self.strength = new_strength; - } -} - -impl<T> Drop for Firework<T> 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 8ad5042ff7b..00000000000 --- 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 3244e1e3afd..00000000000 --- 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 854fa062967..00000000000 --- 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::<false>()); - - let f = |x: bool| { - debug_assert!( - x - ); - }; - f(false); -} - -#[inline] -fn live<const B: bool>() -> 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 9cfab9ddbad..00000000000 --- 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<T: Copy + Display>(xs: &[T]) { - let mut ys = xs.to_owned(); - permutate(&mut ys, 0); -} - -fn permutate<T: Copy + Display>(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<T>(xs: &[T]) -> usize { - xs.len() -} - -#[inline] -fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) { - let t = xs[i]; - xs[i] = xs[j]; - xs[j] = t; -} - -fn display<T: 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 bcb62b3031c..00000000000 --- 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 0b72a81947c..00000000000 --- 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 facf5b5b4cf..00000000000 --- 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 da546cfeef8..00000000000 --- 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<Never> { - None -} - -fn main() {} diff --git a/tests/run-coverage/lazy_boolean.rs b/tests/run-coverage/lazy_boolean.rs deleted file mode 100644 index bb6219e851c..00000000000 --- 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 dbc4fad7a23..00000000000 --- 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 f3a343bcc1f..00000000000 --- 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 ab7aee51d1b..00000000000 --- 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 4c7c7842796..00000000000 --- 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 e12e4bc55e3..00000000000 --- 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 bbb65c1b35d..00000000000 --- 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 638d2eb6aaa..00000000000 --- 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 dd8b42c18ce..00000000000 --- 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 6f7f23475b8..00000000000 --- 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 be99e59a826..00000000000 --- 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/sort_groups.rs b/tests/run-coverage/sort_groups.rs deleted file mode 100644 index f89f9f3ec61..00000000000 --- a/tests/run-coverage/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::<char>(cond); - } - generic_fn::<i32>(cond); - other_fn(); -} - -fn generic_fn<T>(cond: bool) { - if cond { - println!("{}", std::any::type_name::<T>()); - } -} - -fn other_fn() {} diff --git a/tests/run-coverage/test_harness.rs b/tests/run-coverage/test_harness.rs deleted file mode 100644 index 12a755734c1..00000000000 --- 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 cef99027aaa..00000000000 --- 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 557cbf22bfa..00000000000 --- 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<Thing2, ()> { - if return_error { - Err(()) - } else { - Ok(Thing2 {}) - } - } -} - -struct Thing2; -impl Thing2 { - fn call(&self, return_error: bool) -> Result<u32, ()> { - 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 6385bfa160d..00000000000 --- a/tests/run-coverage/unreachable.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![feature(core_intrinsics)] -#![feature(coverage_attribute)] -// compile-flags: --edition=2021 - -// <https://github.com/rust-lang/rust/issues/116171> -// 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 d985af13547..00000000000 --- a/tests/run-coverage/unused.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![allow(dead_code, unused_assignments, unused_must_use, unused_variables)] - -fn foo<T>(x: T) { - let mut i = 0; - while i < 10 { - i != 0 || i != 0; - i += 1; - } -} - -fn unused_template_func<T>(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::<u32>(0); - foo::<f32>(0.0); - Ok(()) -} diff --git a/tests/run-coverage/while.rs b/tests/run-coverage/while.rs deleted file mode 100644 index 781b90b3566..00000000000 --- 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 b2f0eee2cc0..00000000000 --- 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 b7e2ba31b59..00000000000 --- 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/rustdoc-json/doc_hidden_failure.rs b/tests/rustdoc-json/doc_hidden_failure.rs index 0d2c6b2209b..e2ce66c99e4 100644 --- a/tests/rustdoc-json/doc_hidden_failure.rs +++ b/tests/rustdoc-json/doc_hidden_failure.rs @@ -1,8 +1,5 @@ // Regression test for <https://github.com/rust-lang/rust/issues/98007>. -#![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 f2409858057..74d96248d5c 100644 --- a/tests/rustdoc-json/enums/field_hidden.rs +++ b/tests/rustdoc-json/enums/field_hidden.rs @@ -1,11 +1,5 @@ // Regression test for <https://github.com/rust-lang/rust/issues/100529>. -#![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 777161c4e4b..68483683464 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 34a4f4aec53..53cdf83ffa6 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 49990ec5331..bec89530b05 100644 --- a/tests/rustdoc-json/enums/use_glob.rs +++ b/tests/rustdoc-json/enums/use_glob.rs @@ -1,8 +1,5 @@ // Regression test for <https://github.com/rust-lang/rust/issues/104942> -#![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 8190e1cbe81..c7e0c21f1ef 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 3b82561ec7d..8b3a8c0a74e 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 d6ea343b991..eef9ae99eb0 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 539d17f831e..2f6cf3bf65a 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 27d842066f4..8e82efef4be 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 5239a6f21f5..44dc6d854aa 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 9cfe649243f..56d6e7a49db 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 f37ce0abb41..7de1ed78f2f 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 <https://github.com/rust-lang/rust/issues/98003>. -#![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 efa54d91dca..d3c15cd23e4 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 3c6fefc4ca2..fa3a36df856 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 b98d1e4167c..7c68a2412f3 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 d2b0665dcaf..3da03df2546 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 d2ac316d47d..7857626d66e 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 fcd27ca4b7c..836f1fe87da 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 141c54a57dd..97db9c93a0f 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 37a72000329..015e89c2281 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 769dd3f0a2c..acc3a879fe1 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 dc28258a8b6..419b0b4fcab 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 6e105b382b0..549e4c200dc 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 b8279298c1e..917e9e0790c 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 cabee0b1caa..d925fcd5221 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<T_>; - -pub struct Wrapper<T_>(PhantomData<T_>); +pub struct Wrapper<T_>(std::marker::PhantomData<T_>); // @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 81e0acdc6e9..50e23fc06d3 100644 --- a/tests/rustdoc-json/primitives/primitive_overloading.rs +++ b/tests/rustdoc-json/primitives/primitive_overloading.rs @@ -3,14 +3,10 @@ // Regression test for <https://github.com/rust-lang/rust/issues/98006>. #![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 37ca279b352..a8f5500d629 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 <https://github.com/rust-lang/rust/issues/100531> -#![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 dee35ba78dc..9a75f4c0cf3 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 78edfaf0aa8..ed0c4a420d4 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 ae4e87d23bc..11ea5aa3522 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 f81445bd48d..a4133e2f0c7 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 c5c41b25f7e..37f7b26fc85 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 ac0632b98a9..be09cb47629 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 1c49f213d1a..bc072be81a3 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 8c8152bd16c..d7b76623557 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 cdcbf2a2bc8..e6f037eb4b3 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 a2a25d08448..15d194ef5d9 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 <https://github.com/rust-lang/rust/issues/106379> -#![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 00000000000..1b6ff5fadca --- /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 9114460231d..3924282a49e 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 d0fd314bd8c..63693787448 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 6a765b73301..42ba6c40019 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 <https://github.com/rust-lang/rust/issues/107677>. -#![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 a00547dc348..1e1710e1c08 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 <https://github.com/rust-lang/rust/issues/97432>. -#![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 462efee51bf..2ca8c7fa6be 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 1373f96f87f..04611eeb95c 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 0ce81b5e59f..a9301b3fe4f 100644 --- a/tests/rustdoc-json/return_private.rs +++ b/tests/rustdoc-json/return_private.rs @@ -1,9 +1,6 @@ // Regression test for <https://github.com/rust-lang/rust/issues/96161>. // 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 d2664b49e9c..d5ab1173d92 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 7d351ad61be..c27553c7544 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 49238e5e88b..67b5a858ab7 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 2123ac40427..bbae3557cf9 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 64c6c53ce47..f8603147951 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/issues/issue-107918.rs b/tests/rustdoc-ui/issues/issue-107918.rs index 13788df0fc9..0ddb3dc9215 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/const-effect-param.rs b/tests/rustdoc/const-effect-param.rs index f50a9b96d81..b6379c05a85 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/inline_cross/auxiliary/const-effect-param.rs b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs new file mode 100644 index 00000000000..b0c21ffaeb9 --- /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<R: ~const Resource>() -> i32 { + 0 +} + +pub const fn lock<R: Resource>() {} + +#[allow(non_upper_case_globals)] +pub trait Clash<const host: u64> {} + +#[allow(non_upper_case_globals)] +pub const fn clash<T: Clash<host>, 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 26332b419b6..00000000000 --- 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 00000000000..1d003e28f36 --- /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<R>() -> 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<R>()\ +// 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<T, const host: u64>()\ +// where \ +// T: Clash<host>" +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 24934b873c2..00000000000 --- 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-115295-macro-const-display.rs b/tests/rustdoc/issue-115295-macro-const-display.rs new file mode 100644 index 00000000000..2916c7a84a1 --- /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<T> {} + +// @has foo/struct.WithConst.html +pub struct WithConst<const N: usize>; + +macro_rules! spans_from_macro { + () => { + impl WithConst<42> { + pub fn new() -> Self { + Self + } + } + impl Trait<WithConst<42>> for WithConst<42> {} + impl Trait<WithConst<43>> for WithConst<{ 43 }> {} + impl Trait<WithConst<{ 44 }>> for WithConst<44> {} + pub struct Other { + pub field: WithConst<42>, + } + }; +} + +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait<WithConst<41>> for WithConst<41>" +impl Trait<WithConst<41>> for WithConst<41> {} + +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl WithConst<42>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait<WithConst<42>> for WithConst<42>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait<WithConst<43>> for WithConst<{ 43 }>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait<WithConst<44>> for WithConst<44>" + +// @has foo/struct.Other.html +// @has - //pre "pub field: WithConst<42>" +spans_from_macro!(); diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs index 3d6cff00a6d..685a029dcb2 100644 --- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs @@ -130,7 +130,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) { 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, movability: Movability::Movable, diff --git a/tests/ui/async-await/no-async-const.rs b/tests/ui/async-await/no-async-const.rs index 963460c1182..c9941d1c5a0 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 a51dc88a4ed..524d778c09b 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-unsafe-async.rs b/tests/ui/async-await/no-unsafe-async.rs index f40154e16f3..7c6811d81ee 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 f23d17d6bfa..49b112f9313 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/atomic-from-mut-not-available.stderr b/tests/ui/atomic-from-mut-not-available.stderr index d1ebca8a29e..c15d19b1594 100644 --- a/tests/ui/atomic-from-mut-not-available.stderr +++ b/tests/ui/atomic-from-mut-not-available.stderr @@ -3,6 +3,10 @@ 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 diff --git a/tests/ui/auto-traits/has-arguments.rs b/tests/ui/auto-traits/has-arguments.rs new file mode 100644 index 00000000000..f579eb6772d --- /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 00000000000..3bba74badbc --- /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 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 00000000000..0c30931a1b5 --- /dev/null +++ b/tests/ui/auto-traits/issue-117789.rs @@ -0,0 +1,7 @@ +#![deny(suspicious_auto_trait_impls)] + +auto trait Trait<P> {} //~ ERROR auto traits cannot have generic parameters +//~^ ERROR auto traits are experimental and possibly buggy +impl<P> Trait<P> 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 00000000000..9a3a7efed3e --- /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<P> {} + | -----^^^ 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<P> {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #13231 <https://github.com/rust-lang/rust/issues/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/binop/binary-op-suggest-deref.fixed b/tests/ui/binop/binary-op-suggest-deref.fixed new file mode 100644 index 00000000000..1ff3599137b --- /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 00000000000..12505a9ac27 --- /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 00000000000..1b7e45c7724 --- /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 previous error + +For more information about this error, try `rustc --explain E0308`. 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 00000000000..b47372c9064 --- /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 00000000000..14671de7e51 --- /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 00000000000..fca042b1c57 --- /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 previous error + +For more information about this error, try `rustc --explain E0070`. 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 914ebbe26a5..106485e04ee 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 00000000000..c83ba41976b --- /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 <https://github.com/rust-lang/rust/issues/70861> + = note: `#[warn(pointer_structural_match)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr index 0807f459029..85426dd9a5e 100644 --- a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr @@ -5,10 +5,10 @@ LL | let _b = || { match l1 { L1::A => () } }; | ^^ pattern `L1::B` not covered | note: `L1` defined here - --> $DIR/non-exhaustive-match.rs:12:14 + --> $DIR/non-exhaustive-match.rs:12:6 | LL | enum L1 { A, B } - | -- ^ not covered + | ^^ - not covered = note: the matched value is of type `L1` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/consts/assert-type-intrinsics.rs b/tests/ui/consts/assert-type-intrinsics.rs index b4fd423becd..32b5f5c92c5 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 3c03b03deee..66c4f0f9cd6 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/const-blocks/fn-call-in-non-const.stderr b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr index 174103eeba4..eb8b8ac7534 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,13 +6,17 @@ LL | let _: [Option<Bar>; 2] = [no_copy(); 2]; | = note: required for `Option<Bar>` 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 <https://github.com/rust-lang/rfcs/pull/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<Bar> = no_copy(); +LL ~ let _: [Option<Bar>; 2] = [ARRAY_REPEAT_VALUE; 2]; + | error: aborting due to previous error diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 06fa4b0b1f3..858ffa820e2 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -10,9 +10,13 @@ note: required for `Foo<String>` 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 <https://github.com/rust-lang/rfcs/pull/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<String> = Foo(String::new()); +LL ~ [ARRAY_REPEAT_VALUE; 4]; + | error: aborting due to previous error diff --git a/tests/ui/consts/const-fn-in-vec.rs b/tests/ui/consts/const-fn-in-vec.rs index a40290eca09..0483800efef 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<String>; 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<String>; 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 9eb7524b504..4593034bfae 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<String>; 5] = [None; 5]; + | ^^^^ the trait `Copy` is not implemented for `String` | + = note: required for `Option<String>` 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 <https://github.com/rust-lang/rfcs/pull/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<String> = None; +LL ~ static _MAYBE_STRINGS: [Option<String>; 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 <https://github.com/rust-lang/rfcs/pull/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<String>; 5] = [None; 5]; + | ^^^^ the trait `Copy` is not implemented for `String` + | + = note: required for `Option<String>` 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 <https://github.com/rust-lang/rfcs/pull/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<String> = None; +LL ~ let _maybe_strings: [Option<String>; 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_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 00000000000..2491071d1e1 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs @@ -0,0 +1,32 @@ +#![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"; + +fn main() { + match D { + D => {} //~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 00000000000..ab53346b5ee --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr @@ -0,0 +1,34 @@ +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 <https://github.com/rust-lang/rust/issues/70861> +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 <https://github.com/rust-lang/rust/issues/70861> + +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:28: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 <https://github.com/rust-lang/rust/issues/70861> + +error: aborting due to 3 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 96e8795e52d..aaf1edb6fe6 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 731ef509cca..441aeecbc6d 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/issue-34784.rs b/tests/ui/consts/issue-34784.rs deleted file mode 100644 index 98d943470a7..00000000000 --- 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/coroutine/issue-57084.rs b/tests/ui/coroutine/issue-57084.rs index 95bed5b151e..e0aeae66735 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/witness-ignore-fake-reads.rs b/tests/ui/coroutine/witness-ignore-fake-reads.rs new file mode 100644 index 00000000000..ccf9ce8b49e --- /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: Send>(_: T) {} +fn main() { + is_send(next()) +} 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 00000000000..ffeb02d78b8 --- /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<Ordering> { + 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<Ordering> { + 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 00000000000..c538061b365 --- /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 0cfe03869af..bb1fab343a3 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -36,6 +36,7 @@ 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 diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout index 3d9f8129d93..42154c3c3be 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<T: ::core::marker::Copy + Trait, U: ::core::marker::Copy> #[automatically_derived] impl<T: ::core::fmt::Debug + Trait, U: ::core::fmt::Debug> ::core::fmt::Debug for Generic<T, U> 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<T: ::core::fmt::Debug + ::core::marker::Copy + Trait, U: ::core::fmt::Debug + ::core::marker::Copy> ::core::fmt::Debug for PackedGeneric<T, U> 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<T: ::core::marker::Copy, U: ::core::marker::Copy> ::core::marker::Copy #[automatically_derived] impl<T: ::core::fmt::Debug, U: ::core::fmt::Debug> ::core::fmt::Debug for EnumGeneric<T, U> { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { EnumGeneric::One(__self_0) => diff --git a/tests/ui/error-codes/E0004.stderr b/tests/ui/error-codes/E0004.stderr index 603bc5237ea..ced478d65ea 100644 --- a/tests/ui/error-codes/E0004.stderr +++ b/tests/ui/error-codes/E0004.stderr @@ -5,12 +5,12 @@ LL | match x { | ^ pattern `Terminator::HastaLaVistaBaby` not covered | note: `Terminator` defined here - --> $DIR/E0004.rs:2:5 + --> $DIR/E0004.rs:1:6 | LL | enum Terminator { - | ---------- + | ^^^^^^^^^^ LL | HastaLaVistaBaby, - | ^^^^^^^^^^^^^^^^ not covered + | ---------------- not covered = note: the matched value is of type `Terminator` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | 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 eb61c4cf159..8af0eedc82b 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 @@ -134,13 +134,13 @@ LL | match Foo::A { | ^^^^^^ pattern `Foo::C` not covered | note: `Foo` defined here - --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:16:9 + --> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:13:10 | LL | enum Foo { - | --- + | ^^^ ... LL | C, - | ^ not covered + | - not covered = note: the matched value is of type `Foo` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | 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 00000000000..e19dcf9f6a5 --- /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 00000000000..893f7870237 --- /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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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/generic-associated-types/assume-gat-normalization-for-nested-goals.rs b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs index 7b168707239..e2d51c6649a 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 00000000000..abad0f25c0f --- /dev/null +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `<Self as Foo>::Bar<()>: Eq<i32>` is not satisfied + --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:30 + | +LL | type Bar<T>: Baz<Self> = i32; + | ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>` + | +note: required for `i32` to implement `Baz<Self>` + --> $DIR/assume-gat-normalization-for-nested-goals.rs:13:23 + | +LL | impl<T: Foo + ?Sized> Baz<T> for i32 where T::Bar<()>: Eq<i32> {} + | ^^^^^^ ^^^ ------- 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<T>: Baz<Self> = i32; + | ^^^^^^^^^ required by this bound in `Foo::Bar` +help: consider further restricting the associated type + | +LL | trait Foo where <Self as Foo>::Bar<()>: Eq<i32> { + | +++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. 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 00000000000..5ef9437c968 --- /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 + // `<Any as HasValue<'r>>::Database = Any` isn't universally + // parameterized over `'r`. + type Database = Any; +} + +fn main() {} diff --git a/tests/ui/generic-const-items/const-trait-impl.rs b/tests/ui/generic-const-items/const-trait-impl.rs index d30f7af170d..43cdf818c46 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: ~const Create>: T = T::create(); +// FIXME(generic_const_items, effects): Introduce `const` bounds to make this work. +const CREATE<T: Create>: T = T::create(); pub const K0: i32 = CREATE::<i32>; 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 34360c581d5..64aa8adf8a7 100644 --- a/tests/ui/generic-const-items/const-trait-impl.stderr +++ b/tests/ui/generic-const-items/const-trait-impl.stderr @@ -1,8 +1,8 @@ error[E0015]: cannot call non-const fn `<T as Create>::create` in constants - --> $DIR/const-trait-impl.rs:11:37 + --> $DIR/const-trait-impl.rs:11:30 | -LL | const CREATE<T: ~const Create>: T = T::create(); - | ^^^^^^^^^^^ +LL | const CREATE<T: Create>: T = T::create(); + | ^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 1fd61084130..e0dc13c0c95 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/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 00000000000..af6ffe83394 --- /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 `<Self as MyTrait>::{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 00000000000..7c9028a8cd5 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr @@ -0,0 +1,14 @@ +error[E0310]: the associated type `<Self as MyTrait>::{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 `<Self as MyTrait>::{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 `<Self as MyTrait>::{opaque#0}: 'static`... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr index 6ea6bb600e9..3041c2c99a1 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<u8>` + = note: 1 redundant requirement hidden + = note: required for `[{integer}; 1]` to implement `Index<u8>` 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 00000000000..e9c429b53ce --- /dev/null +++ b/tests/ui/indexing/point-at-index-for-obligation-failure.rs @@ -0,0 +1,7 @@ +fn main() { + let a = std::collections::HashMap::<String,String>::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 00000000000..3e2fbc2ab6f --- /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<str>` is implemented for `String` + = help: for that trait implementation, expected `str`, found `&str` + = note: required for `HashMap<String, String>` to implement `Index<&&str>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. 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 00000000000..be017a3f94f --- /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/macros/stringify.rs b/tests/ui/macros/stringify.rs index f1bbd4a6210..70ca00285c4 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -115,6 +115,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 +138,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 {}", @@ -799,3 +801,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/match/match_non_exhaustive.stderr b/tests/ui/match/match_non_exhaustive.stderr index 7b8bdfe0053..40be39ec077 100644 --- a/tests/ui/match/match_non_exhaustive.stderr +++ b/tests/ui/match/match_non_exhaustive.stderr @@ -5,10 +5,10 @@ LL | match l { L::A => () }; | ^ pattern `L::B` not covered | note: `L` defined here - --> $DIR/match_non_exhaustive.rs:10:13 + --> $DIR/match_non_exhaustive.rs:10:6 | LL | enum L { A, B } - | - ^ not covered + | ^ - not covered = note: the matched value is of type `L` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr index a9e9c679fdb..ccdd9a95451 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 | <T as A>::foo(&s); - | ~~~~~~~~~~ -LL | <T as B>::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 | <T as A>::CONST; +LL | <S as A>::CONST; | ~~~~~~~~~~ -LL | <T as B>::CONST; +LL | <S as B>::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 901bfc30a3f..4172120770c 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 | <S as A>::foo(&s); - | ~~~~~~~~~~ -LL | <S as B>::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 0f9c60ce243..2778f254a56 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 _ = <T as A>::CONST; + | ~~~~~~~~~~ +LL | let _ = <T as B>::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 | <T as A>::foo(&s); - | ~~~~~~~~~~ -LL | <T as B>::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 _ = <T as A>::CONST; +LL | let _ = <S as A>::CONST; | ~~~~~~~~~~ -LL | let _ = <T as B>::CONST; +LL | let _ = <S as B>::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 9a50d51245b..e00498ca62b 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 | <T as A>::foo(&s); - | ~~~~~~~~~~ -LL | <T as B>::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 _ = <T as A>::CONST; +LL | let _ = <S as A>::CONST; | ~~~~~~~~~~ -LL | let _ = <T as B>::CONST; +LL | let _ = <S as B>::CONST; | ~~~~~~~~~~ error: aborting due to 3 previous errors 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 601e6bbb006..9a84768a9f4 100644 --- a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr +++ b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr @@ -16,12 +16,12 @@ 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 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 4e83e4b77f1..755179650bb 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/mir/addrof_alignment.rs b/tests/ui/mir/alignment/addrof_alignment.rs index 892638bfb92..f3423e97a8a 100644 --- a/tests/ui/mir/addrof_alignment.rs +++ b/tests/ui/mir/alignment/addrof_alignment.rs @@ -1,5 +1,4 @@ // run-pass -// ignore-wasm32-bare: No panic messages // compile-flags: -C debug-assertions struct Misalignment { @@ -9,7 +8,7 @@ struct Misalignment { fn main() { let items: [Misalignment; 2] = [Misalignment { a: 0 }, Misalignment { a: 1 }]; unsafe { - let ptr: *const Misalignment = items.as_ptr().cast::<u8>().add(1).cast::<Misalignment>(); + let ptr: *const Misalignment = items.as_ptr().byte_add(1); let _ptr = core::ptr::addr_of!((*ptr).a); } } diff --git a/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs b/tests/ui/mir/alignment/i686-pc-windows-msvc.rs index 56388c1047e..74ba1fde649 100644 --- a/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs +++ b/tests/ui/mir/alignment/i686-pc-windows-msvc.rs @@ -11,9 +11,9 @@ fn main() { let mut x = [0u64; 2]; - let ptr: *mut u8 = x.as_mut_ptr().cast::<u8>(); + let ptr = x.as_mut_ptr(); unsafe { - let misaligned = ptr.add(4).cast::<u64>(); + let misaligned = ptr.byte_add(4); assert!(misaligned.addr() % 8 != 0); assert!(misaligned.addr() % 4 == 0); *misaligned = 42; diff --git a/tests/ui/mir/mir_alignment_check.rs b/tests/ui/mir/alignment/misaligned_lhs.rs index d1bf3d46a7c..97644ba8e09 100644 --- a/tests/ui/mir/mir_alignment_check.rs +++ b/tests/ui/mir/alignment/misaligned_lhs.rs @@ -6,8 +6,8 @@ fn main() { let mut x = [0u32; 2]; - let ptr: *mut u8 = x.as_mut_ptr().cast::<u8>(); + let ptr = x.as_mut_ptr(); unsafe { - *(ptr.add(1).cast::<u32>()) = 42; + *(ptr.byte_add(1)) = 42; } } diff --git a/tests/ui/mir/alignment/misaligned_rhs.rs b/tests/ui/mir/alignment/misaligned_rhs.rs new file mode 100644 index 00000000000..8534bc71a3a --- /dev/null +++ b/tests/ui/mir/alignment/misaligned_rhs.rs @@ -0,0 +1,13 @@ +// run-fail +// ignore-wasm32-bare: No panic messages +// ignore-i686-pc-windows-msvc: #112480 +// compile-flags: -C debug-assertions +// error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is + +fn main() { + let mut x = [0u32; 2]; + let ptr = x.as_mut_ptr(); + unsafe { + let _v = *(ptr.byte_add(1)); + } +} diff --git a/tests/ui/mir/alignment/packed.rs b/tests/ui/mir/alignment/packed.rs new file mode 100644 index 00000000000..754698591e3 --- /dev/null +++ b/tests/ui/mir/alignment/packed.rs @@ -0,0 +1,29 @@ +// run-pass +// compile-flags: -C debug-assertions + +#![feature(strict_provenance, pointer_is_aligned)] + +#[repr(packed)] +struct Misaligner { + _head: u8, + tail: u64, +} + +fn main() { + let memory = [Misaligner { _head: 0, tail: 0}, Misaligner { _head: 0, tail: 0}]; + // Test that we can use addr_of! to get the address of a packed member which according to its + // type is not aligned, but because it is a projection from a packed type is a valid place. + let ptr0 = std::ptr::addr_of!(memory[0].tail); + let ptr1 = std::ptr::addr_of!(memory[0].tail); + // Even if ptr0 happens to be aligned by chance, ptr1 is not. + assert!(!ptr0.is_aligned() || !ptr1.is_aligned()); + + // And also test that we can get the addr of a packed struct then do a member read from it. + unsafe { + let ptr = std::ptr::addr_of!(memory[0]); + let _tail = (*ptr).tail; + + let ptr = std::ptr::addr_of!(memory[1]); + let _tail = (*ptr).tail; + } +} diff --git a/tests/ui/mir/alignment/place_computation.rs b/tests/ui/mir/alignment/place_computation.rs new file mode 100644 index 00000000000..fdd4864250a --- /dev/null +++ b/tests/ui/mir/alignment/place_computation.rs @@ -0,0 +1,16 @@ +// run-pass +// compile-flags: -C debug-assertions + +#[repr(align(8))] +struct Misalignment { + a: u8, +} + +fn main() { + let mem = 0u64; + let ptr = &mem as *const u64 as *const Misalignment; + unsafe { + let ptr = ptr.byte_add(1); + let _ref: &u8 = &(*ptr).a; + } +} diff --git a/tests/ui/mir/alignment/place_without_read.rs b/tests/ui/mir/alignment/place_without_read.rs new file mode 100644 index 00000000000..b4be7a50f61 --- /dev/null +++ b/tests/ui/mir/alignment/place_without_read.rs @@ -0,0 +1,9 @@ +// run-pass +// compile-flags: -C debug-assertions + +fn main() { + let ptr = 1 as *const u16; + unsafe { + let _ = *ptr; + } +} diff --git a/tests/ui/mir/alignment/two_pointers.rs b/tests/ui/mir/alignment/two_pointers.rs new file mode 100644 index 00000000000..29af21dffc1 --- /dev/null +++ b/tests/ui/mir/alignment/two_pointers.rs @@ -0,0 +1,15 @@ +// run-fail +// ignore-wasm32-bare: No panic messages +// ignore-i686-pc-windows-msvc: #112480 +// compile-flags: -C debug-assertions +// error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is + +fn main() { + let x = [0u32; 2]; + let ptr = x.as_ptr(); + let mut dest = 0u32; + let dest_ptr = &mut dest as *mut u32; + unsafe { + *dest_ptr = *(ptr.byte_add(1)); + } +} 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 00000000000..1787f80c07e --- /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 00000000000..3d18c249afe --- /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 previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/mir/ssa_call_ret.rs b/tests/ui/mir/ssa_call_ret.rs new file mode 100644 index 00000000000..6132a6691de --- /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/noncleanup-cleanup.rs b/tests/ui/mir/validate/noncleanup-cleanup.rs new file mode 100644 index 00000000000..0a1c4528aa6 --- /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 00000000000..e80d09bc90a --- /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 00000000000..2a74668370d --- /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/nll/closure-requirements/escape-argument-callee.stderr b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr index b3cb7813e19..a8f6559e425 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<Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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<Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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)), (), ] diff --git a/tests/ui/nll/closure-requirements/escape-argument.stderr b/tests/ui/nll/closure-requirements/escape-argument.stderr index 4f0156728ac..40f04bb6da6 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<Region(BrAnon), Region(BrAnon)> 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<Region(BrAnon), Region(BrAnon)> 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)), (), ] 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 ccf56bf6f37..ef2cb4067d7 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<Region(BrAnon), Region(BrAnon)> 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<Region(BrAnon), Region(BrAnon)> 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 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr index a16433c9d37..db48a4ce70c 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<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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 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 9e0f16c0fc7..5ce3dae5a33 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<Region(BrAnon)> extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), + for<Region(BrAnon)> 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<Region(BrAnon)> extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), + for<Region(BrAnon)> 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 e4989e32155..ffd526d90af 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<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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 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 be35e62d070..726d0dc2a4c 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<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr index 8880dd816a1..5a65c768448 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<Region(BrAnon), Region(BrAnon)> 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<Region(BrAnon), Region(BrAnon)> 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-despite-same-free-region.stderr b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index 47774b63f81..0dd53f81ae1 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<Region(BrAnon), Region(BrAnon)> 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<Region(BrAnon), Region(BrAnon)> 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 3404bb12827..f7a0ee9b18d 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<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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 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 e40648912e3..fa9fa9e8f3c 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<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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<Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon), Region(BrAnon)> 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 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 18fb7195d02..35e4a16c8da 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<Region(BrAnon), Region(BrAnon)> 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<Region(BrAnon), Region(BrAnon)> 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, (), ] 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 00000000000..5227ca8ec17 --- /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: Fn(&()) -> &()>(_: 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 00000000000..5227ca8ec17 --- /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: Fn(&()) -> &()>(_: 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 00000000000..c165e7a1d1a --- /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: Fn(&()) -> &()>(_: F) {} 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 59e29e9a420..0048eef6779 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::<T>::{closure#0} with closure args [ i16, - for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), + for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) ()>>, &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::<T>::{closure#0} with closure args [ i16, - for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), + for<Region(BrAnon), Region(BrAnon)> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) ()>>, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), (), ] = note: late-bound region is '?2 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 00000000000..475b41388d3 --- /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/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs index e8b5a08377b..a2d6aace47d 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-private.rs b/tests/ui/offset-of/offset-of-private.rs index 6fa30d63fb8..b7affdb7943 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/parser/brace-in-let-chain.rs b/tests/ui/parser/brace-in-let-chain.rs new file mode 100644 index 00000000000..1f34c73a2c3 --- /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 00000000000..7182d86d001 --- /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/emoji-identifiers.stderr b/tests/ui/parser/emoji-identifiers.stderr index e645b68ba87..8250dd1ea2e 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/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 00000000000..eaae288864a --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +pub fn func<F>() 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 00000000000..ea5c71150e8 --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs @@ -0,0 +1,8 @@ +// run-rustfix + +pub fn func<F>() 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 00000000000..7cda667570d --- /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<F>() where F: FnOnce -> () {} + | -------^^ expected one of `(`, `+`, `,`, `::`, `<`, or `{` + | | | + | | help: try adding parentheses + | `Fn` bounds require arguments in parentheses + +error: aborting due to 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 df0cd54399a..099178a7d50 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 977c6ebfef3..4c55179ce23 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 00000000000..9d7fe43893e --- /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 00000000000..3f504a9ebfc --- /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 bbebc99e94b..47942662685 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 f455caba158..489e8eefb05 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 4ff4cf5c8ca..867f71c1204 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-const.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs index 2f5fbc513ee..9a7f28210f9 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-unsafe.rs b/tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs index df2412e3e9b..8305ff4f623 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/semi-in-let-chain.rs b/tests/ui/parser/semi-in-let-chain.rs new file mode 100644 index 00000000000..9c21af0372d --- /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 00000000000..c1a8f92965e --- /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/pattern/issue-94866.stderr b/tests/ui/pattern/issue-94866.stderr index b3c17ce8974..dee4b3f557c 100644 --- a/tests/ui/pattern/issue-94866.stderr +++ b/tests/ui/pattern/issue-94866.stderr @@ -5,10 +5,10 @@ LL | match Enum::A { | ^^^^^^^ pattern `Enum::B` not covered | note: `Enum` defined here - --> $DIR/issue-94866.rs:7:16 + --> $DIR/issue-94866.rs:7:6 | LL | enum Enum { A, B } - | ---- ^ not covered + | ^^^^ - not covered = note: the matched value is of type `Enum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.rs b/tests/ui/pattern/usefulness/conflicting_bindings.rs new file mode 100644 index 00000000000..0b3e7ce9e9a --- /dev/null +++ b/tests/ui/pattern/usefulness/conflicting_bindings.rs @@ -0,0 +1,24 @@ +#![feature(if_let_guard, let_chains)] + +fn main() { + let mut x = Some(String::new()); + let ref mut y @ ref mut z = x; + //~^ ERROR: mutable more than once + let Some(ref mut y @ ref mut z) = x else { return }; + //~^ ERROR: mutable more than once + if let Some(ref mut y @ ref mut z) = x {} + //~^ ERROR: mutable more than once + if let Some(ref mut y @ ref mut z) = x && true {} + //~^ ERROR: mutable more than once + while let Some(ref mut y @ ref mut z) = x {} + //~^ ERROR: mutable more than once + while let Some(ref mut y @ ref mut z) = x && true {} + //~^ ERROR: mutable more than once + match x { + ref mut y @ ref mut z => {} //~ ERROR: mutable more than once + } + match () { + () if let Some(ref mut y @ ref mut z) = x => {} //~ ERROR: mutable more than once + _ => {} + } +} diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.stderr b/tests/ui/pattern/usefulness/conflicting_bindings.stderr new file mode 100644 index 00000000000..679fc83e7f5 --- /dev/null +++ b/tests/ui/pattern/usefulness/conflicting_bindings.stderr @@ -0,0 +1,66 @@ +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:5:9 + | +LL | let ref mut y @ ref mut z = x; + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:7:14 + | +LL | let Some(ref mut y @ ref mut z) = x else { return }; + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:9:17 + | +LL | if let Some(ref mut y @ ref mut z) = x {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:11:17 + | +LL | if let Some(ref mut y @ ref mut z) = x && true {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:13:20 + | +LL | while let Some(ref mut y @ ref mut z) = x {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:15:20 + | +LL | while let Some(ref mut y @ ref mut z) = x && true {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:18:9 + | +LL | ref mut y @ ref mut z => {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:21:24 + | +LL | () if let Some(ref mut y @ ref mut z) = x => {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: aborting due to 8 previous errors + diff --git a/tests/ui/pattern/usefulness/consts-opaque.rs b/tests/ui/pattern/usefulness/consts-opaque.rs index 6dc1425cf03..27e305a3972 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<Quux> = 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<Quux> = 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 51f2f276bbe..09f72ba927e 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 <https://github.com/rust-lang/rust/issues/70861> + = 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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + 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<fn(usize, usize) -> usize>` defined here - --> $DIR/consts-opaque.rs:104:12 + --> $DIR/consts-opaque.rs:106:12 | LL | struct Wrap<T>(T); | ^^^^ = note: the matched value is of type `Wrap<fn(usize, usize) -> 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/doc-hidden-non-exhaustive.stderr b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr index ff29de03d6b..24f3eaa5230 100644 --- a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr +++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr @@ -23,13 +23,13 @@ LL | match HiddenEnum::A { | ^^^^^^^^^^^^^ pattern `HiddenEnum::B` not covered | note: `HiddenEnum` defined here - --> $DIR/auxiliary/hidden.rs:3:5 + --> $DIR/auxiliary/hidden.rs:1:1 | LL | pub enum HiddenEnum { - | ------------------- + | ^^^^^^^^^^^^^^^^^^^ LL | A, LL | B, - | ^ not covered + | - not covered = note: the matched value is of type `HiddenEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -44,13 +44,13 @@ LL | match HiddenEnum::A { | ^^^^^^^^^^^^^ patterns `HiddenEnum::B` and `_` not covered | note: `HiddenEnum` defined here - --> $DIR/auxiliary/hidden.rs:3:5 + --> $DIR/auxiliary/hidden.rs:1:1 | LL | pub enum HiddenEnum { - | ------------------- + | ^^^^^^^^^^^^^^^^^^^ LL | A, LL | B, - | ^ not covered + | - not covered = note: the matched value is of type `HiddenEnum` 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 | @@ -83,13 +83,13 @@ LL | match InCrate::A { | ^^^^^^^^^^ pattern `InCrate::C` not covered | note: `InCrate` defined here - --> $DIR/doc-hidden-non-exhaustive.rs:11:5 + --> $DIR/doc-hidden-non-exhaustive.rs:7:6 | LL | enum InCrate { - | ------- + | ^^^^^^^ ... LL | C, - | ^ not covered + | - not covered = note: the matched value is of type `InCrate` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index 5b81a8c3d3c..8f9bd5bde89 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/empty-match.rs:58:9 + --> $DIR/empty-match.rs:68:9 | LL | _ => {}, | ^ @@ -11,25 +11,25 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-match.rs:61:9 + --> $DIR/empty-match.rs:71:9 | LL | _ if false => {}, | ^ error: unreachable pattern - --> $DIR/empty-match.rs:68:9 + --> $DIR/empty-match.rs:78:9 | LL | _ => {}, | ^ error: unreachable pattern - --> $DIR/empty-match.rs:71:9 + --> $DIR/empty-match.rs:81:9 | LL | _ if false => {}, | ^ error[E0005]: refutable pattern in local binding - --> $DIR/empty-match.rs:76:9 + --> $DIR/empty-match.rs:86:9 | LL | let None = x; | ^^^^ pattern `Some(_)` not covered @@ -44,19 +44,19 @@ LL | if let None = x { todo!() }; | ++ +++++++++++ error: unreachable pattern - --> $DIR/empty-match.rs:88:9 + --> $DIR/empty-match.rs:98:9 | LL | _ => {}, | ^ error: unreachable pattern - --> $DIR/empty-match.rs:91:9 + --> $DIR/empty-match.rs:101:9 | LL | _ if false => {}, | ^ error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/empty-match.rs:109:20 + --> $DIR/empty-match.rs:119:20 | LL | match_no_arms!(0u8); | ^^^ @@ -65,7 +65,7 @@ LL | match_no_arms!(0u8); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty - --> $DIR/empty-match.rs:111:20 + --> $DIR/empty-match.rs:121:20 | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:113:20 + --> $DIR/empty-match.rs:123:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -93,7 +93,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:115:20 + --> $DIR/empty-match.rs:125:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -107,7 +107,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:117:20 + --> $DIR/empty-match.rs:127:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,42 +121,44 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:119:20 + --> $DIR/empty-match.rs:129:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:33:5 + --> $DIR/empty-match.rs:32:6 | LL | enum NonEmptyEnum1 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:122:20 + --> $DIR/empty-match.rs:132:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:40:5 + --> $DIR/empty-match.rs:39:6 | LL | enum NonEmptyEnum2 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered ... LL | Bar, - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:125:20 + --> $DIR/empty-match.rs:135:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -166,11 +168,19 @@ note: `NonEmptyEnum5` defined here | LL | enum NonEmptyEnum5 { | ^^^^^^^^^^^^^ +... +LL | V1, V2, V3, V4, V5, + | -- -- -- -- -- not covered + | | | | | + | | | | not covered + | | | not covered + | | not covered + | not covered = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:129:24 + --> $DIR/empty-match.rs:139:24 | LL | match_guarded_arm!(0u8); | ^^^ pattern `_` not covered @@ -184,7 +194,7 @@ LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:134:24 + --> $DIR/empty-match.rs:144:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -203,7 +213,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:139:24 + --> $DIR/empty-match.rs:149:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -222,7 +232,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:144:24 + --> $DIR/empty-match.rs:154:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -241,7 +251,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:149:24 + --> $DIR/empty-match.rs:159:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -260,18 +270,19 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:154:24 + --> $DIR/empty-match.rs:164:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:33:5 + --> $DIR/empty-match.rs:32:6 | LL | enum NonEmptyEnum1 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = 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 @@ -281,21 +292,22 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:159:24 + --> $DIR/empty-match.rs:169:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:40:5 + --> $DIR/empty-match.rs:39:6 | LL | enum NonEmptyEnum2 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered ... LL | Bar, - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = 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 @@ -305,7 +317,7 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:164:24 + --> $DIR/empty-match.rs:174:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -315,6 +327,14 @@ note: `NonEmptyEnum5` defined here | LL | enum NonEmptyEnum5 { | ^^^^^^^^^^^^^ +... +LL | V1, V2, V3, V4, V5, + | -- -- -- -- -- not covered + | | | | | + | | | | not covered + | | | not covered + | | not covered + | not covered = note: the matched value is of type `NonEmptyEnum5` = 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 as shown, or multiple match arms diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index 6d17455086b..7f0389f40e2 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/empty-match.rs:58:9 + --> $DIR/empty-match.rs:68:9 | LL | _ => {}, | ^ @@ -11,25 +11,25 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-match.rs:61:9 + --> $DIR/empty-match.rs:71:9 | LL | _ if false => {}, | ^ error: unreachable pattern - --> $DIR/empty-match.rs:68:9 + --> $DIR/empty-match.rs:78:9 | LL | _ => {}, | ^ error: unreachable pattern - --> $DIR/empty-match.rs:71:9 + --> $DIR/empty-match.rs:81:9 | LL | _ if false => {}, | ^ error[E0005]: refutable pattern in local binding - --> $DIR/empty-match.rs:76:9 + --> $DIR/empty-match.rs:86:9 | LL | let None = x; | ^^^^ pattern `Some(_)` not covered @@ -43,19 +43,19 @@ LL | if let None = x { todo!() }; | ++ +++++++++++ error: unreachable pattern - --> $DIR/empty-match.rs:88:9 + --> $DIR/empty-match.rs:98:9 | LL | _ => {}, | ^ error: unreachable pattern - --> $DIR/empty-match.rs:91:9 + --> $DIR/empty-match.rs:101:9 | LL | _ if false => {}, | ^ error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/empty-match.rs:109:20 + --> $DIR/empty-match.rs:119:20 | LL | match_no_arms!(0u8); | ^^^ @@ -64,7 +64,7 @@ LL | match_no_arms!(0u8); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty - --> $DIR/empty-match.rs:111:20 + --> $DIR/empty-match.rs:121:20 | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:113:20 + --> $DIR/empty-match.rs:123:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:115:20 + --> $DIR/empty-match.rs:125:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,7 +106,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:117:20 + --> $DIR/empty-match.rs:127:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -120,42 +120,44 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:119:20 + --> $DIR/empty-match.rs:129:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:33:5 + --> $DIR/empty-match.rs:32:6 | LL | enum NonEmptyEnum1 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:122:20 + --> $DIR/empty-match.rs:132:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:40:5 + --> $DIR/empty-match.rs:39:6 | LL | enum NonEmptyEnum2 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered ... LL | Bar, - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:125:20 + --> $DIR/empty-match.rs:135:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -165,11 +167,19 @@ note: `NonEmptyEnum5` defined here | LL | enum NonEmptyEnum5 { | ^^^^^^^^^^^^^ +... +LL | V1, V2, V3, V4, V5, + | -- -- -- -- -- not covered + | | | | | + | | | | not covered + | | | not covered + | | not covered + | not covered = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:129:24 + --> $DIR/empty-match.rs:139:24 | LL | match_guarded_arm!(0u8); | ^^^ pattern `_` not covered @@ -183,7 +193,7 @@ LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:134:24 + --> $DIR/empty-match.rs:144:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -202,7 +212,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:139:24 + --> $DIR/empty-match.rs:149:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -221,7 +231,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:144:24 + --> $DIR/empty-match.rs:154:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -240,7 +250,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:149:24 + --> $DIR/empty-match.rs:159:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -259,18 +269,19 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:154:24 + --> $DIR/empty-match.rs:164:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:33:5 + --> $DIR/empty-match.rs:32:6 | LL | enum NonEmptyEnum1 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = 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 @@ -280,21 +291,22 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:159:24 + --> $DIR/empty-match.rs:169:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:40:5 + --> $DIR/empty-match.rs:39:6 | LL | enum NonEmptyEnum2 { - | ------------- + | ^^^^^^^^^^^^^ +... LL | Foo(bool), - | ^^^ not covered + | --- not covered ... LL | Bar, - | ^^^ not covered + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = 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 @@ -304,7 +316,7 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:164:24 + --> $DIR/empty-match.rs:174:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -314,6 +326,14 @@ note: `NonEmptyEnum5` defined here | LL | enum NonEmptyEnum5 { | ^^^^^^^^^^^^^ +... +LL | V1, V2, V3, V4, V5, + | -- -- -- -- -- not covered + | | | | | + | | | | not covered + | | | not covered + | | not covered + | not covered = note: the matched value is of type `NonEmptyEnum5` = 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 as shown, or multiple match arms diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs index d56d2e3c817..fe5d0bce14f 100644 --- a/tests/ui/pattern/usefulness/empty-match.rs +++ b/tests/ui/pattern/usefulness/empty-match.rs @@ -30,17 +30,17 @@ union NonEmptyUnion2 { bar: (), } enum NonEmptyEnum1 { - Foo(bool), //~^ NOTE `NonEmptyEnum1` defined here //~| NOTE `NonEmptyEnum1` defined here - //~| NOTE not covered + Foo(bool), + //~^ NOTE not covered //~| NOTE not covered } enum NonEmptyEnum2 { - Foo(bool), //~^ NOTE `NonEmptyEnum2` defined here //~| NOTE `NonEmptyEnum2` defined here - //~| NOTE not covered + Foo(bool), + //~^ NOTE not covered //~| NOTE not covered Bar, //~^ NOTE not covered @@ -50,6 +50,16 @@ enum NonEmptyEnum5 { //~^ NOTE `NonEmptyEnum5` defined here //~| NOTE `NonEmptyEnum5` defined here V1, V2, V3, V4, V5, + //~^ NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered } fn empty_enum(x: EmptyEnum) { diff --git a/tests/ui/pattern/usefulness/issue-35609.stderr b/tests/ui/pattern/usefulness/issue-35609.stderr index 6d5e2f410bc..9feedfde469 100644 --- a/tests/ui/pattern/usefulness/issue-35609.stderr +++ b/tests/ui/pattern/usefulness/issue-35609.stderr @@ -107,6 +107,9 @@ LL | match Some(A) { | note: `Option<Enum>` defined here --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered = note: the matched value is of type `Option<Enum>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | diff --git a/tests/ui/pattern/usefulness/issue-39362.stderr b/tests/ui/pattern/usefulness/issue-39362.stderr index b8b17918aef..8dc53491606 100644 --- a/tests/ui/pattern/usefulness/issue-39362.stderr +++ b/tests/ui/pattern/usefulness/issue-39362.stderr @@ -5,12 +5,12 @@ LL | match f { | ^ patterns `Foo::Bar { bar: Bar::C, .. }`, `Foo::Bar { bar: Bar::D, .. }`, `Foo::Bar { bar: Bar::E, .. }` and 1 more not covered | note: `Foo` defined here - --> $DIR/issue-39362.rs:2:5 + --> $DIR/issue-39362.rs:1:6 | LL | enum Foo { - | --- + | ^^^ LL | Bar { bar: Bar, id: usize } - | ^^^ not covered + | --- not covered = note: the matched value is of type `Foo` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | diff --git a/tests/ui/pattern/usefulness/issue-40221.stderr b/tests/ui/pattern/usefulness/issue-40221.stderr index 4973e42b054..40b42af26b3 100644 --- a/tests/ui/pattern/usefulness/issue-40221.stderr +++ b/tests/ui/pattern/usefulness/issue-40221.stderr @@ -5,12 +5,12 @@ LL | match proto { | ^^^^^ pattern `P::C(PC::QA)` not covered | note: `P` defined here - --> $DIR/issue-40221.rs:2:5 + --> $DIR/issue-40221.rs:1:6 | LL | enum P { - | - + | ^ LL | C(PC), - | ^ not covered + | - not covered = note: the matched value is of type `P` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/issue-56379.stderr b/tests/ui/pattern/usefulness/issue-56379.stderr index b3e40b99239..50e13bdfdfe 100644 --- a/tests/ui/pattern/usefulness/issue-56379.stderr +++ b/tests/ui/pattern/usefulness/issue-56379.stderr @@ -5,16 +5,16 @@ LL | match Foo::A(true) { | ^^^^^^^^^^^^ patterns `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered | note: `Foo` defined here - --> $DIR/issue-56379.rs:2:5 + --> $DIR/issue-56379.rs:1:6 | LL | enum Foo { - | --- + | ^^^ LL | A(bool), - | ^ not covered + | - not covered LL | B(bool), - | ^ not covered + | - not covered LL | C(bool), - | ^ not covered + | - not covered = note: the matched value is of type `Foo` 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 | diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs index 5145f769075..1d1ea8e4964 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs @@ -1,10 +1,15 @@ +#![feature(custom_inner_attributes)] +#![rustfmt::skip] // Test the "defined here" and "not covered" diagnostic hints. // We also make sure that references are peeled off from the scrutinee type // so that the diagnostics work better with default binding modes. #[derive(Clone)] enum E { - //~^ NOTE + //~^ NOTE `E` defined here + //~| NOTE `E` defined here + //~| NOTE `E` defined here + //~| NOTE //~| NOTE //~| NOTE //~| NOTE @@ -12,10 +17,7 @@ enum E { //~| NOTE A, B, - //~^ NOTE `E` defined here - //~| NOTE `E` defined here - //~| NOTE `E` defined here - //~| NOTE not covered + //~^ NOTE not covered //~| NOTE not covered //~| NOTE not covered //~| NOTE not covered @@ -79,12 +81,12 @@ fn by_ref_thrice(e: & &mut &E) { } enum Opt { - //~^ NOTE + //~^ NOTE `Opt` defined here + //~| NOTE //~| NOTE Some(u8), None, - //~^ NOTE `Opt` defined here - //~| NOTE not covered + //~^ NOTE not covered //~| NOTE not covered } diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr index 8489e2f14b8..a9e55fa53a6 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr @@ -1,20 +1,20 @@ error[E0004]: non-exhaustive patterns: `E::B` and `E::C` not covered - --> $DIR/non-exhaustive-defined-here.rs:35:11 + --> $DIR/non-exhaustive-defined-here.rs:37:11 | LL | match e1 { | ^^ patterns `E::B` and `E::C` not covered | note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:14:5 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { - | - + | ^ ... LL | B, - | ^ not covered + | - not covered ... LL | C - | ^ not covered + | - not covered = note: the matched value is of type `E` 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 | @@ -23,7 +23,7 @@ LL + E::B | E::C => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/non-exhaustive-defined-here.rs:41:9 + --> $DIR/non-exhaustive-defined-here.rs:43:9 | LL | let E::A = e; | ^^^^ patterns `E::B` and `E::C` not covered @@ -31,7 +31,7 @@ LL | let E::A = e; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:6:6 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { | ^ @@ -48,22 +48,22 @@ LL | if let E::A = e { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered - --> $DIR/non-exhaustive-defined-here.rs:50:11 + --> $DIR/non-exhaustive-defined-here.rs:52:11 | LL | match e { | ^ patterns `&E::B` and `&E::C` not covered | note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:14:5 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { - | - + | ^ ... LL | B, - | ^ not covered + | - not covered ... LL | C - | ^ not covered + | - not covered = note: the matched value is of type `&E` 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 | @@ -72,7 +72,7 @@ LL + &E::B | &E::C => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/non-exhaustive-defined-here.rs:57:9 + --> $DIR/non-exhaustive-defined-here.rs:59:9 | LL | let E::A = e; | ^^^^ patterns `&E::B` and `&E::C` not covered @@ -80,7 +80,7 @@ LL | let E::A = e; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:6:6 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { | ^ @@ -97,22 +97,22 @@ LL | if let E::A = e { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered - --> $DIR/non-exhaustive-defined-here.rs:66:11 + --> $DIR/non-exhaustive-defined-here.rs:68:11 | LL | match e { | ^ patterns `&&mut &E::B` and `&&mut &E::C` not covered | note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:14:5 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { - | - + | ^ ... LL | B, - | ^ not covered + | - not covered ... LL | C - | ^ not covered + | - not covered = note: the matched value is of type `&&mut &E` 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 | @@ -121,7 +121,7 @@ LL + &&mut &E::B | &&mut &E::C => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/non-exhaustive-defined-here.rs:73:9 + --> $DIR/non-exhaustive-defined-here.rs:75:9 | LL | let E::A = e; | ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered @@ -129,7 +129,7 @@ LL | let E::A = e; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `E` defined here - --> $DIR/non-exhaustive-defined-here.rs:6:6 + --> $DIR/non-exhaustive-defined-here.rs:8:6 | LL | enum E { | ^ @@ -146,19 +146,19 @@ LL | if let E::A = e { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: `Opt::None` not covered - --> $DIR/non-exhaustive-defined-here.rs:92:11 + --> $DIR/non-exhaustive-defined-here.rs:94:11 | LL | match e { | ^ pattern `Opt::None` not covered | note: `Opt` defined here - --> $DIR/non-exhaustive-defined-here.rs:85:5 + --> $DIR/non-exhaustive-defined-here.rs:83:6 | LL | enum Opt { - | --- + | ^^^ ... LL | None, - | ^^^^ not covered + | ---- not covered = note: the matched value is of type `Opt` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -167,7 +167,7 @@ LL + Opt::None => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/non-exhaustive-defined-here.rs:99:9 + --> $DIR/non-exhaustive-defined-here.rs:101:9 | LL | let Opt::Some(ref _x) = e; | ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered @@ -175,7 +175,7 @@ LL | let Opt::Some(ref _x) = e; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `Opt` defined here - --> $DIR/non-exhaustive-defined-here.rs:81:6 + --> $DIR/non-exhaustive-defined-here.rs:83:6 | LL | enum Opt { | ^^^ diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr index 98e417a17f8..310049fe13e 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr @@ -18,10 +18,10 @@ LL | match x { | ^ pattern `T::A(U::C)` not covered | note: `T` defined here - --> $DIR/non-exhaustive-match-nested.rs:1:10 + --> $DIR/non-exhaustive-match-nested.rs:1:6 | LL | enum T { A(U), B } - | - ^ not covered + | ^ - not covered = note: the matched value is of type `T` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr index e59e8885e1a..4bebd3cbbef 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr @@ -5,10 +5,10 @@ LL | match x { T::B => { } } | ^ pattern `T::A` not covered | note: `T` defined here - --> $DIR/non-exhaustive-match.rs:3:10 + --> $DIR/non-exhaustive-match.rs:3:6 | LL | enum T { A, B } - | - ^ not covered + | ^ - not covered = note: the matched value is of type `T` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -79,10 +79,10 @@ LL | match T::A { | ^^^^ pattern `T::B` not covered | note: `T` defined here - --> $DIR/non-exhaustive-match.rs:3:13 + --> $DIR/non-exhaustive-match.rs:3:6 | LL | enum T { A, B } - | - ^ not covered + | ^ - not covered = note: the matched value is of type `T` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr index f914b98d923..cceb1d8f65d 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr @@ -23,12 +23,12 @@ LL | match Color::Red { | ^^^^^^^^^^ pattern `Color::Red` not covered | note: `Color` defined here - --> $DIR/non-exhaustive-pattern-witness.rs:17:5 + --> $DIR/non-exhaustive-pattern-witness.rs:16:6 | LL | enum Color { - | ----- + | ^^^^^ LL | Red, - | ^^^ not covered + | --- not covered = note: the matched value is of type `Color` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | @@ -43,17 +43,17 @@ LL | match Direction::North { | ^^^^^^^^^^^^^^^^ patterns `Direction::East`, `Direction::South` and `Direction::West` not covered | note: `Direction` defined here - --> $DIR/non-exhaustive-pattern-witness.rs:32:5 + --> $DIR/non-exhaustive-pattern-witness.rs:30:6 | LL | enum Direction { - | --------- + | ^^^^^^^^^ LL | North, LL | East, - | ^^^^ not covered + | ---- not covered LL | South, - | ^^^^^ not covered + | ----- not covered LL | West, - | ^^^^ not covered + | ---- not covered = note: the matched value is of type `Direction` 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 | @@ -72,6 +72,17 @@ note: `ExcessiveEnum` defined here | LL | enum ExcessiveEnum { | ^^^^^^^^^^^^^ +LL | First, +LL | Second, + | ------ not covered +LL | Third, + | ----- not covered +LL | Fourth, + | ------ not covered +LL | Fifth, + | ----- not covered +LL | Sixth, + | ----- not covered = note: the matched value is of type `ExcessiveEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | @@ -86,13 +97,13 @@ LL | match Color::Red { | ^^^^^^^^^^ pattern `Color::CustomRGBA { a: true, .. }` not covered | note: `Color` defined here - --> $DIR/non-exhaustive-pattern-witness.rs:19:5 + --> $DIR/non-exhaustive-pattern-witness.rs:16:6 | LL | enum Color { - | ----- + | ^^^^^ ... LL | CustomRGBA { a: bool, r: u8, g: u8, b: u8 }, - | ^^^^^^^^^^ not covered + | ---------- not covered = note: the matched value is of type `Color` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr index f944c25a905..f75517fb791 100644 --- a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr +++ b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr @@ -5,13 +5,13 @@ LL | match UnstableEnum::Stable { | ^^^^^^^^^^^^^^^^^^^^ patterns `UnstableEnum::Stable2` and `_` not covered | note: `UnstableEnum` defined here - --> $DIR/auxiliary/unstable.rs:9:5 + --> $DIR/auxiliary/unstable.rs:5:1 | LL | pub enum UnstableEnum { - | --------------------- + | ^^^^^^^^^^^^^^^^^^^^^ ... LL | Stable2, - | ^^^^^^^ not covered + | ------- not covered = note: the matched value is of type `UnstableEnum` 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 | diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr index 22425aa0dd4..3d2b540a9f5 100644 --- a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr +++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr @@ -5,12 +5,12 @@ LL | match x { | ^ pattern `A::B { x: Some(_) }` not covered | note: `A` defined here - --> $DIR/struct-like-enum-nonexhaustive.rs:2:5 + --> $DIR/struct-like-enum-nonexhaustive.rs:1:6 | LL | enum A { - | - + | ^ LL | B { x: Option<isize> }, - | ^ not covered + | - not covered = note: the matched value is of type `A` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr index d776249b231..4a4945156f7 100644 --- a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr +++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr @@ -5,13 +5,13 @@ LL | match UnstableEnum::Stable { | ^^^^^^^^^^^^^^^^^^^^ pattern `UnstableEnum::Unstable` not covered | note: `UnstableEnum` defined here - --> $DIR/auxiliary/unstable.rs:11:5 + --> $DIR/auxiliary/unstable.rs:5:1 | LL | pub enum UnstableEnum { - | --------------------- + | ^^^^^^^^^^^^^^^^^^^^^ ... LL | Unstable, - | ^^^^^^^^ not covered + | -------- not covered = note: the matched value is of type `UnstableEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | 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 00000000000..4f6290808fc --- /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 00000000000..39adc0fde44 --- /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 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr index 730fd6d6026..9d0439d9d87 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::<T>::new + Box::<T>::new_uninit + Box::<T>::new_zeroed + Box::<T>::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/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 2b3fbd2a4d2..e591b2a93e1 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<fn()> = Wrap(trivial); let input: Wrap<fn()> = 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<fn(SM)> = Wrap(sm_to); let input: Wrap<fn(SM)> = 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<fn() -> SM> = Wrap(to_sm); let input: Wrap<fn() -> 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<fn(NotSM)> = Wrap(not_sm_to); let input: Wrap<fn(NotSM)> = 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<fn() -> NotSM> = Wrap(to_not_sm); let input: Wrap<fn() -> 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<fn(&SM)> = Wrap(r_sm_to); let input: Wrap<fn(&SM)> = 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<fn(&()) -> &SM> = Wrap(r_to_r_sm); let input: Wrap<fn(&()) -> &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<fn(&NotSM)> = Wrap(r_not_sm_to); let input: Wrap<fn(&NotSM)> = 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<fn(&()) -> &NotSM> = Wrap(r_to_r_not_sm); let input: Wrap<fn(&()) -> &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 00000000000..080bf5885ba --- /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 <https://github.com/rust-lang/rust/issues/70861> + = 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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +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 <https://github.com/rust-lang/rust/issues/70861> + +warning: 10 warnings emitted + 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 567685950e9..b05b8c8da1f 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 d6afc0255ec..4fdfce60bb8 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 <https://github.com/rust-lang/rust/issues/70861> + +warning: 2 warnings emitted diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr index de1bf8be885..7386f10a6fb 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr @@ -17,18 +17,18 @@ LL | match NonExhaustiveEnum::Unit {} | ^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered | note: `NonExhaustiveEnum` defined here - --> $DIR/enum_same_crate_empty_match.rs:5:5 + --> $DIR/enum_same_crate_empty_match.rs:4:10 | LL | pub enum NonExhaustiveEnum { - | ----------------- + | ^^^^^^^^^^^^^^^^^ LL | Unit, - | ^^^^ not covered + | ---- not covered LL | LL | Tuple(u32), - | ^^^^^ not covered + | ----- not covered LL | LL | Struct { field: u32 } - | ^^^^^^ not covered + | ------ not covered = note: the matched value is of type `NonExhaustiveEnum` 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 | @@ -44,18 +44,18 @@ LL | match NormalEnum::Unit {} | ^^^^^^^^^^^^^^^^ patterns `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered | note: `NormalEnum` defined here - --> $DIR/enum_same_crate_empty_match.rs:14:5 + --> $DIR/enum_same_crate_empty_match.rs:13:10 | LL | pub enum NormalEnum { - | ---------- + | ^^^^^^^^^^ LL | Unit, - | ^^^^ not covered + | ---- not covered LL | LL | Tuple(u32), - | ^^^^^ not covered + | ----- not covered LL | LL | Struct { field: u32 } - | ^^^^^^ not covered + | ------ not covered = note: the matched value is of type `NormalEnum` 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 | diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr new file mode 100644 index 00000000000..9192c66143c --- /dev/null +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr @@ -0,0 +1,75 @@ +error: some variants are not matched explicitly + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:15:11 + | +LL | match val { + | ^^^ 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-dont-lint-on-arm.rs:14:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:23:11 + | +LL | match val { + | ^^^ 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-dont-lint-on-arm.rs:22:27 + | +LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: the lint level must be set on the whole match + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ------------------------------- remove this attribute +LL | _ => {} + | ^ + | + = help: it no longer has any effect to set the lint level on an individual match arm +help: set the lint level on the whole match + | +LL + #[deny(non_exhaustive_omitted_patterns)] +LL | match val { + | + +warning: the lint level must be set on the whole match + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:42:9 + | +LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] + | ------------------------------- remove this attribute +LL | _ => {} + | ^ + | + = help: it no longer has any effect to set the lint level on an individual match arm +help: set the lint level on the whole match + | +LL + #[deny(non_exhaustive_omitted_patterns)] +LL | match val { + | + +warning: the lint level must be set on the whole match + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:50:9 + | +LL | #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))] + | ------------------------------- remove this attribute +LL | _ => {} + | ^ + | + = help: it no longer has any effect to set the lint level on an individual match arm +help: set the lint level on the whole match + | +LL + #[warn(non_exhaustive_omitted_patterns)] +LL | match val { + | + +error: aborting due to 2 previous errors; 3 warnings emitted + 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 new file mode 100644 index 00000000000..46093eb9fb3 --- /dev/null +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr @@ -0,0 +1,31 @@ +error: some variants are not matched explicitly + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:15:11 + | +LL | match val { + | ^^^ 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-dont-lint-on-arm.rs:14:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: the lint level must be set on the whole match + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ------------------------------- remove this attribute +LL | _ => {} + | ^ + | + = help: it no longer has any effect to set the lint level on an individual match arm +help: set the lint level on the whole match + | +LL + #[deny(non_exhaustive_omitted_patterns)] +LL | match val { + | + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs new file mode 100644 index 00000000000..33f9f56a5bb --- /dev/null +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs @@ -0,0 +1,53 @@ +// revisions: normal lint +// Test that putting the lint level on a match arm emits a warning, as this was previously +// meaningful and is no longer. +#![feature(non_exhaustive_omitted_patterns_lint)] + +// aux-build:enums.rs +extern crate enums; + +use enums::NonExhaustiveEnum; + +fn main() { + let val = NonExhaustiveEnum::Unit; + + #[deny(non_exhaustive_omitted_patterns)] + match val { + //~^ ERROR some variants are not matched explicitly + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + _ => {} + } + + #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] + match val { + //[lint]~^ ERROR some variants are not matched explicitly + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + _ => {} + } + + match val { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ WARN lint level must be set on the whole match + + match val { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] + _ => {} + } + //[lint]~^^ WARN lint level must be set on the whole match + + match val { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))] + _ => {} + } + //[lint]~^^ WARN lint level must be set on the whole match +} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr index a9c54af0418..c125756a646 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -62,14 +62,14 @@ LL | match x {} | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered | note: `UninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:17:23 + --> $DIR/auxiliary/uninhabited.rs:16:1 | LL | pub enum UninhabitedVariants { - | ---------------------------- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | #[non_exhaustive] Tuple(!), - | ^^^^^ not covered + | ----- not covered LL | #[non_exhaustive] Struct { x: ! } - | ^^^^^^ not covered + | ------ not covered = note: the matched value is of type `UninhabitedVariants` 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 | diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr index ec2a2f6f055..7a12aca8520 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr @@ -43,14 +43,14 @@ LL | match x {} | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered | note: `UninhabitedVariants` defined here - --> $DIR/match_same_crate.rs:16:23 + --> $DIR/match_same_crate.rs:15:10 | LL | pub enum UninhabitedVariants { - | ------------------- + | ^^^^^^^^^^^^^^^^^^^ LL | #[non_exhaustive] Tuple(!), - | ^^^^^ not covered + | ----- not covered LL | #[non_exhaustive] Struct { x: ! } - | ^^^^^^ not covered + | ------ not covered = note: the matched value is of type `UninhabitedVariants` 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 | diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index b6b777ec56c..19e2546b0da 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -62,14 +62,14 @@ LL | match x {} | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered | note: `UninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:17:23 + --> $DIR/auxiliary/uninhabited.rs:16:1 | LL | pub enum UninhabitedVariants { - | ---------------------------- + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | #[non_exhaustive] Tuple(!), - | ^^^^^ not covered + | ----- not covered LL | #[non_exhaustive] Struct { x: ! } - | ^^^^^^ not covered + | ------ not covered = note: the matched value is of type `UninhabitedVariants` 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 | 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 6d436018bf4..e6b663c47d7 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 | <T as Foo>::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 0cffae1da8d..7df16ca5a3b 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/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 index 1e22ddcea8d..0025449c492 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 index 9210f642706..9210f642706 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 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 23e36887025..be75e852e0a 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: ~const Destruct>(_: 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<T: ~const SomeTrait>(pub core::marker::PhantomData<T>); + | ^^^^^^^^^^^^^^^^ | -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 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 0a9cf638a2d..9da84cdb052 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<T: ~const SomeTrait>(pub core::marker::PhantomData<T>); impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> { 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 23e36887025..be75e852e0a 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: ~const Destruct>(_: 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<T: ~const SomeTrait>(pub core::marker::PhantomData<T>); + | ^^^^^^^^^^^^^^^^ | -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 previous error -For more information about this error, try `rustc --explain E0493`. 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 00000000000..6598d1da0f8 --- /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 00000000000..002d586ac64 --- /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 previous error + +For more information about this error, try `rustc --explain E0015`. 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 00000000000..1954d2942e0 --- /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>(T); + +impl<T> Bar<T> { + const fn value() -> usize { + 42 + } +} + +struct Foo<const N: [u8; Bar::<u32>::value()]>; + +pub fn main() {} 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 21ddf4ab4e5..00000000000 --- 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<T>() 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 b2a9365378b..00000000000 --- 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<T>() 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<T>() where T: ~const Bar {} - | ^^^ - -error: aborting due to 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 3db59631ef8..234b0dd0063 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<T> Bar for T +impl<T> const Bar for T where T: ~const Foo, { 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 b60399c57dc..204f0f9f89f 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 5d34156a519..06330958b8e 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 `<T as Foo>::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 -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 eb12a236d8c..77b13a351e2 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<T: ~const Bar>(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 16c592830d7..5994057b2db 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<T: ~const Bar>(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 58225b94591..2e41eb9b4c4 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<T: ~const Bar>(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 6bc643e6871..d81d9aa94da 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,5 +1,5 @@ error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions - --> $DIR/super-traits-fail-3.rs:19:7 + --> $DIR/super-traits-fail-3.rs:20:7 | LL | x.a(); | ^^^ 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 95f7aaba0fc..bbe1194f7a3 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<T: ~const ?Sized>(std::marker::PhantomData<T>); -//~^ ERROR `~const` and `?` are mutually exclusive +#[const_trait] +trait Trait {} + +// Regression test for issue #90052. +fn non_const_function<T: ~const Trait>() {} //~ ERROR `~const` is not allowed + +struct Struct<T: ~const Trait> { field: T } //~ ERROR `~const` is not allowed here +struct TupleStruct<T: ~const Trait>(T); //~ ERROR `~const` is not allowed here +struct UnitStruct<T: ~const Trait>; //~ ERROR `~const` is not allowed here + +enum Enum<T: ~const Trait> { Variant(T) } //~ ERROR `~const` is not allowed here + +union Union<T: ~const Trait> { field: T } //~ ERROR `~const` is not allowed here + +type Type<T: ~const Trait> = T; //~ ERROR `~const` is not allowed here + +const CONSTANT<T: ~const Trait>: () = (); //~ ERROR `~const` is not allowed here +//~^ ERROR generic const items are experimental + +trait NonConstTrait { + type Type<T: ~const Trait>: ~const Trait; + //~^ ERROR `~const` is not allowed + //~| ERROR `~const` is not allowed + fn non_const_function<T: ~const Trait>(); //~ ERROR `~const` is not allowed + const CONSTANT<T: ~const Trait>: (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +impl NonConstTrait for () { + type Type<T: ~const Trait> = (); //~ ERROR `~const` is not allowed + fn non_const_function<T: ~const Trait>() {} //~ ERROR `~const` is not allowed + const CONSTANT<T: ~const Trait>: () = (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +struct Implementor; + +impl Implementor { + type Type<T: ~const Trait> = (); //~ ERROR `~const` is not allowed + //~^ ERROR inherent associated types are unstable + fn non_const_function<T: ~const Trait>() {} //~ ERROR `~const` is not allowed + const CONSTANT<T: ~const Trait>: () = (); //~ 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<T: ~const Trait> 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 d20f146df3f..c14f9a99035 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<T: ~const ?Sized>(std::marker::PhantomData<T>); - | ^^^^^^^^^^^^^ +LL | fn non_const_function<T: ~const Trait>() {} + | ^^^^^^^^^^^^ + | +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<T: ~const Trait>() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:9:18 + | +LL | struct Struct<T: ~const Trait> { 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: ~const Trait>(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<T: ~const Trait>; + | ^^^^^^^^^^^^ + | + = 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<T: ~const Trait> { 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<T: ~const Trait> { 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: ~const Trait> = 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<T: ~const Trait>: () = (); + | ^^^^^^^^^^^^ + | + = 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<T: ~const Trait>: ~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<T: ~const Trait>: ~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<T: ~const Trait>(); + | ^^^^^^^^^^^^ + | +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<T: ~const Trait>(); + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:27:23 + | +LL | const CONSTANT<T: ~const Trait>: (); + | ^^^^^^^^^^^^ + | + = 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<T: ~const Trait> = (); + | ^^^^^^^^^^^^ + | + = 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<T: ~const Trait>() {} + | ^^^^^^^^^^^^ + | +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<T: ~const Trait>() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:34:23 + | +LL | const CONSTANT<T: ~const Trait>: () = (); + | ^^^^^^^^^^^^ + | + = 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<T: ~const Trait> = (); + | ^^^^^^^^^^^^ + | + = 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<T: ~const Trait>() {} + | ^^^^^^^^^^^^ + | +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<T: ~const Trait>() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:44:23 + | +LL | const CONSTANT<T: ~const Trait>: () = (); + | ^^^^^^^^^^^^ + | + = 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<T: ~const Trait> 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<T: ~const Trait> Trait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:19:15 + | +LL | const CONSTANT<T: ~const Trait>: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 <https://github.com/rust-lang/rust/issues/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<T: ~const Trait>: (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 <https://github.com/rust-lang/rust/issues/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<T: ~const Trait>: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 <https://github.com/rust-lang/rust/issues/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<T: ~const Trait>: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 <https://github.com/rust-lang/rust/issues/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<T: ~const Trait> = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 <https://github.com/rust-lang/rust/issues/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 00000000000..ed911d965d6 --- /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<T: ~const ?Sized>() {} +//~^ 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 00000000000..ce74ff8dde7 --- /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<T: ~const ?Sized>() {} + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/span/issue-37767.stderr b/tests/ui/span/issue-37767.stderr index b612fdf16fc..457870821a1 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/structs/method-chain-expression-failure.rs b/tests/ui/structs/method-chain-expression-failure.rs new file mode 100644 index 00000000000..43ebc5bac8c --- /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 00000000000..ba635ab1fe6 --- /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 previous error + +For more information about this error, try `rustc --explain E0599`. 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 128160f10ad..2dd6fb6a3bf 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::<Vec<i32>>().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<i32>` | 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/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index 1cc37d61151..0372a7e6cc0 100644 --- a/tests/ui/suggestions/deref-path-method.stderr +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -4,6 +4,13 @@ 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::<T>::new + Vec::<T>::with_capacity + Vec::<T>::from_raw_parts + Vec::<T, A>::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); diff --git a/tests/ui/suggestions/import-trait-for-method-call.rs b/tests/ui/suggestions/import-trait-for-method-call.rs index 4dbadbdf982..feb2c7e84f1 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/issue-109291.stderr b/tests/ui/suggestions/issue-109291.stderr index 4ef5948d9bf..644841fdf7e 100644 --- a/tests/ui/suggestions/issue-109291.stderr +++ b/tests/ui/suggestions/issue-109291.stderr @@ -6,6 +6,13 @@ 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 diff --git a/tests/ui/suggestions/issue-117669.rs b/tests/ui/suggestions/issue-117669.rs new file mode 100644 index 00000000000..09b4f2bd47c --- /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 00000000000..f09675fcc5c --- /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<i32>` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Option<i32>` +help: consider using `Option::expect` to unwrap the `Option<i32>` value, panicking if the value is an `Option::None` + | +LL | let abs: i32 = 3i32.checked_abs().expect("REASON"); + | +++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. 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 00000000000..84315ad9173 --- /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<T: Any>(value: &T) -> Box<dyn Any + '_> { + Box::new(value) as Box<dyn Any> + //~^ 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 index bbbbf72dbd5..fa7e72ff2a7 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<T: Any>(value: &T) -> Box<dyn Any> { diff --git a/tests/ui/issues/issue-16922.stderr b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.stderr index 9d9f32a97c0..dc5817bfe0f 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<T: Any>(value: &T) -> Box<dyn Any> { | - let's call the lifetime of this reference `'1` diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr index adf01339972..23f6657f092 100644 --- a/tests/ui/suggestions/suggest-dereferencing-index.stderr +++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr @@ -8,6 +8,8 @@ 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]; diff --git a/tests/ui/target-feature/similar-feature-suggestion.stderr b/tests/ui/target-feature/similar-feature-suggestion.stderr index 2f376065fdf..f39dfd401e0 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/unstable-feature.rs b/tests/ui/target-feature/unstable-feature.rs new file mode 100644 index 00000000000..bd0d72938f4 --- /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 00000000000..d34544c5c27 --- /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/thread-local/thread-local-static.stderr b/tests/ui/thread-local/thread-local-static.mir.stderr index 712050a25fc..607d7ee902c 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 c7fee9e6b4c..afaffbb7e9b 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 00000000000..607d7ee902c --- /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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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/traits/new-solver/specialization-transmute.rs b/tests/ui/traits/new-solver/specialization-transmute.rs index f6b19e7adf5..fac7d76f8cf 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<T> 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 09b1405fefb..18965a465b3 100644 --- a/tests/ui/traits/new-solver/specialization-transmute.stderr +++ b/tests/ui/traits/new-solver/specialization-transmute.stderr @@ -16,6 +16,13 @@ LL | fn intu(&self) -> &Self::Id { | = note: cannot satisfy `<T as Default>::Id == _` -error: aborting due to previous error; 1 warning emitted +error[E0282]: type annotations needed + --> $DIR/specialization-transmute.rs:13:23 + | +LL | default type Id = T; + | ^ cannot infer type for associated type `<T as Default>::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/specialization-unconstrained.rs b/tests/ui/traits/new-solver/specialization-unconstrained.rs index 02150689ee5..7fd753109be 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<T> Default for T { - default type Id = T; + default type Id = T; //~ ERROR type annotations needed } fn test<T: Default<Id = U>, U>() {} diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.stderr b/tests/ui/traits/new-solver/specialization-unconstrained.stderr index 910925cbaeb..ed4dafa1484 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<T: Default<Id = U>, 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 `<T as Default>::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/non-lifetime-via-dyn-builtin.current.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr new file mode 100644 index 00000000000..9f373cc50f0 --- /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 <https://github.com/rust-lang/rust/issues/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 00000000000..9f373cc50f0 --- /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 <https://github.com/rust-lang/rust/issues/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 00000000000..9a8a5ced2e2 --- /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<A>() +where + for<B> dyn Fn(A, *const B): Fn(A, *const B), +{ +} + +fn main() { + trivial::<u8>(); +} 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 00000000000..b999f251d33 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs @@ -0,0 +1,19 @@ +// check-pass + +trait Foo { + type Bar<T> + where + dyn Send + 'static: Send; +} + +impl Foo for () { + type Bar<T> = i32; + // We take `<() as Foo>::Bar<T>: Sized` and normalize it under the where clause + // of `for<S> <() as Foo>::Bar<S> = 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/object/print_vtable_sizes.stdout b/tests/ui/traits/object/print_vtable_sizes.stdout index ce90c76217b..b43e168df3f 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": "<UNKNOWN_CRATE>", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" } -print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" } -print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" } -print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "help::MarkerWithSuper", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "help::Super", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "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/type-alias-impl-trait/indirect-recursion-issue-112047.rs b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs index f6cbbf04d82..6a2ee761e19 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 2063becdb08..80b6aaaf919 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,14 +1,22 @@ -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 `<impl at $DIR/indirect-recursion-issue-112047.rs:19:1: 19:18>::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 `<impl at $DIR/indirect-recursion-issue-112047.rs:18:1: 18:18>::recur` + --> $DIR/indirect-recursion-issue-112047.rs:21:5 | LL | fn recur(self) -> Self::Recur { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/union/union-unsafe.mir.stderr b/tests/ui/union/union-unsafe.mir.stderr index 544213dbc55..15f059ffa48 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 5e1837a901d..d1465486f77 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<String> + a: ManuallyDrop<String>, } union U3<T> { - a: ManuallyDrop<T> + a: ManuallyDrop<T>, } union U4<T: Copy> { - 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<RefCell<i32>>, 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 f959fe5bdb5..9ce835497c5 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/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr index fbc621f4d0e..ea53bf59d31 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 a192f3445f7..1b429955cb0 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 00000000000..d63843ed2b3 --- /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/ranged_ints2.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr index 427843f8d45..dc6bd72f56c 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 9a6bb18f926..ad9d598aba2 100644 --- a/tests/ui/unsafe/ranged_ints2.rs +++ b/tests/ui/unsafe/ranged_ints2.rs @@ -9,4 +9,5 @@ pub(crate) struct NonZero<T>(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 427843f8d45..dc6bd72f56c 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/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr index 4cdd97e5e06..ad0621a1d04 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/wrapping-unsafe-block-sugg.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed index db1c102210e..b59029df642 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 index 43f619c27d2..7a1b83c7367 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 9c6be45896e..3629b8a1beb 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 00000000000..b59029df642 --- /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 00000000000..b1fb35f85a6 --- /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/where-clauses/higher-ranked-fn-type.verbose.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr index 54afeaa7eda..782e7dc5e00 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<Region(BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b))> 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<Region(BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b))> 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<Region(BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b))> 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<Region(BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b))> 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 diff --git a/triagebot.toml b/triagebot.toml index b419727bcfd..4c8c1c59beb 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -415,7 +415,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] @@ -579,7 +579,7 @@ 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"] @@ -608,19 +608,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", "WaffleLapkin", "oli-obk"] [assign.adhoc_groups] compiler-team = [ "@cjgillot", + "@compiler-errors", "@petrochenkov", "@davidtwco", "@oli-obk", "@wesleywiser", ] compiler-team-contributors = [ - "@compiler-errors", - "@jackh726", "@TaKO8Ki", "@WaffleLapkin", "@b-naber", |
