diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8cc26d2995e7..5f659a1c3060 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 d56d7e3f2b03..d3ecadf6e172 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,25 +1281,14 @@ checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys 0.48.0", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "error_index_generator" version = "0.0.0" @@ -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_locid" -version = "1.2.0" +name = "icu_list_data" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3003f85dccfc0e238ff567693248c59153a46f4e6125ba4020b973cef4d1d335" +checksum = "d3237583f0cb7feafabb567c4492fe9ef1d2d4113f6a8798a923273ea5de996d" + +[[package]] +name = "icu_locid" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f284eb342dc49d3e9d9f3b188489d76b5d22dfb1d1a5e0d1941811253bac625c" dependencies = [ "displaydoc", "litemap", @@ -1914,15 +1911,36 @@ dependencies = [ ] [[package]] -name = "icu_provider" -version = "1.2.0" +name = "icu_locid_transform" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc312a7b6148f7dfe098047ae2494d12d4034f48ade58d4f353000db376e305" +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.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +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]] @@ -5216,18 +5233,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] - [[package]] name = "synstructure" version = "0.13.0" @@ -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 1cc110e6607f..a0f6b1203fca 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,120 @@ +Version 1.74.0 (2023-11-16) +========================== + + + +Language +-------- + +- [Codify that `std::mem::Discriminant` does not depend on any lifetimes in T](https://github.com/rust-lang/rust/pull/104299/) +- [Replace `private_in_public` lint with `private_interfaces` and `private_bounds` per RFC 2145.](https://github.com/rust-lang/rust/pull/113126/) + Read more in [RFC 2145](https://rust-lang.github.io/rfcs/2145-type-privacy.html). +- [Allow explicit `#[repr(Rust)]`](https://github.com/rust-lang/rust/pull/114201/) +- [closure field capturing: don't depend on alignment of packed fields](https://github.com/rust-lang/rust/pull/115315/) +- [Enable MIR-based drop-tracking for `async` blocks](https://github.com/rust-lang/rust/pull/107421/) +- [Stabilize `impl_trait_projections`](https://github.com/rust-lang/rust/pull/115659) + + + +Compiler +-------- + +- [stabilize combining +bundle and +whole-archive link modifiers](https://github.com/rust-lang/rust/pull/113301/) +- [Stabilize `PATH` option for `--print KIND=PATH`](https://github.com/rust-lang/rust/pull/114183/) +- [Enable ASAN/LSAN/TSAN for `*-apple-ios-macabi`](https://github.com/rust-lang/rust/pull/115644/) +- [Promote loongarch64-unknown-none* to Tier 2](https://github.com/rust-lang/rust/pull/115368/) +- [Add `i686-pc-windows-gnullvm` as a tier 3 target](https://github.com/rust-lang/rust/pull/115687/) + + + +Libraries +--------- + +- [Implement `From` for ChildStdin/out/err](https://github.com/rust-lang/rust/pull/98704/) +- [Implement `From<{&,&mut} [T; N]>` for `Vec` where `T: Clone`](https://github.com/rust-lang/rust/pull/111278/) +- [impl Step for IP addresses](https://github.com/rust-lang/rust/pull/113748/) +- [Implement `From<[T; N]>` for `Rc<[T]>` and `Arc<[T]>`](https://github.com/rust-lang/rust/pull/114041/) +- [`impl TryFrom for u16`](https://github.com/rust-lang/rust/pull/114065/) +- [Stabilize `io_error_other` feature](https://github.com/rust-lang/rust/pull/115453/) +- [Stabilize the `Saturating` type](https://github.com/rust-lang/rust/pull/115477/) +- [Stabilize const_transmute_copy](https://github.com/rust-lang/rust/pull/115520/) + + + +Stabilized APIs +--------------- + +- [`core::num::Saturating`](https://doc.rust-lang.org/stable/std/num/struct.Saturating.html) +- [`impl From for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStdout%3E-for-Stdio) +- [`impl From for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) +- [`impl From for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) +- [`impl From for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.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 for u16`](https://doc.rust-lang.org/stable/std/primitive.u16.html#impl-TryFrom%3Cchar%3E-for-u16) +- [`impl From<&[T; N]> for Vec`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#impl-From%3C%26%5BT;+N%5D%3E-for-Vec%3CT,+Global%3E) +- [`impl From<&mut [T; N]> for Vec`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#impl-From%3C%26mut+%5BT;+N%5D%3E-for-Vec%3CT,+Global%3E) +- [`impl From<[T; N]> for Arc<[T]>`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#impl-From%3C%5BT;+N%5D%3E-for-Arc%3C%5BT%5D,+Global%3E) +- [`impl From<[T; N]> for Rc<[T]>`](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#impl-From%3C%5BT;+N%5D%3E-for-Rc%3C%5BT%5D,+Global%3E) + +These APIs are now stable in const contexts: + +- [`core::mem::transmute_copy`](https://doc.rust-lang.org/beta/std/mem/fn.transmute_copy.html) +- [`str::is_ascii`](https://doc.rust-lang.org/beta/std/primitive.str.html#method.is_ascii) +- [`[u8]::is_ascii`](https://doc.rust-lang.org/beta/std/primitive.slice.html#method.is_ascii) + + + +Cargo +----- + +- [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/) + + + +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/) + + + +Compatibility Notes +------------------- + +- [Raise minimum supported Apple OS versions](https://github.com/rust-lang/rust/pull/104385/) +- [make Cell::swap panic if the Cells partially overlap](https://github.com/rust-lang/rust/pull/114795/) +- [Reject invalid crate names in `--extern`](https://github.com/rust-lang/rust/pull/116001/) +- [Don't resolve generic impls that may be shadowed by dyn built-in impls](https://github.com/rust-lang/rust/pull/114941/) +- [The new `impl From<{&,&mut} [T; N]> for Vec` is known to cause some inference failures with overly-generic code.](https://github.com/rust-lang/rust/issues/117054) In those examples using the `tui` crate, the combination of `AsRef<_>` and `Into` leaves the middle type ambiguous, and the new `impl` adds another possibility, so it now requires an explicit type annotation. + + + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + +None this cycle. + Version 1.73.0 (2023-10-05) ========================== diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 9127e1d06e88..996fd5bbecfc 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 8e7aa59ee341..09a87cf8e2f0 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, pub pack: Option, pub flags: ReprFlags, - #[cfg(feature = "randomize")] /// The seed to be used for randomizing a type's layout /// - /// Note: This could technically be a `Hash128` which would + /// Note: This could technically be a `u128` which would /// be the "most accurate" hash as it'd encompass the item and crate /// hash without loss, but it does pay the price of being larger. /// Everything's a tradeoff, a 64-bit seed should be sufficient for our /// purposes (primarily `-Z randomize-layout`) - pub field_shuffle_seed: rustc_data_structures::stable_hasher::Hash64, + pub field_shuffle_seed: u64, } impl ReprOptions { diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 146a4db200ca..c85ff6f5c445 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 0634ee970ec5..7c0a78253a21 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( } ExprKind::Closure(box Closure { binder, - capture_clause: _, + capture_clause, constness, asyncness, movability: _, @@ -1409,6 +1413,7 @@ pub fn noop_visit_expr( 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(visibility: &mut Visibility, vis: &mut T) { vis.visit_span(&mut visibility.span); } +pub fn noop_visit_capture_by(capture_by: &mut CaptureBy, vis: &mut T) { + match capture_by { + CaptureBy::Ref => {} + CaptureBy::Value { move_kw } => { + vis.visit_span(move_kw); + } + } +} + /// Some value for the AST node that is valid but possibly meaningless. pub trait DummyAstNode { fn dummy() -> Self; diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 914c97a14ac0..a6ee93e8a6ba 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 e091961a1443..1caa39e2dd99 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 0fff9a6be926..c07dbbc9d67e 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 c73d2382db80..9a70e6d7c4a1 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 a88493acf982..55d50e5fe6a1 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 d22bae816ef4..876126b02ea9 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 3d0513c89230..ce37f6677cfc 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 d14b62d6bdc6..7f6fcb493171 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 e71f421659e2..48421ff71409 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 e84af12d3f9c..edbc3500373b 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 fb54937a098f..48af4e6f600b 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 57f7496dcff8..000000000000 --- 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 e4aaf50f5d67..000000000000 --- 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 a485a5af64ca..000000000000 --- 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 ce04af868aa5..000000000000 --- 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 a13646a0b925..000000000000 --- 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 9023647138b1..000000000000 --- 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 647f8f516019..000000000000 --- 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 62957134f075..000000000000 --- 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 4bf244019ff1..000000000000 --- 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 84de7cd01a7e..000000000000 --- 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 79a97e50f5a8..000000000000 --- 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 b976b6cb65aa..000000000000 --- 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 d76d567ebf87..000000000000 --- 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 e20941f0c676..000000000000 --- 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 3d8c89f9072f..000000000000 --- 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 653ce28d615a..000000000000 --- 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 9fa6eb56ade2..000000000000 --- 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 66b55c253688..000000000000 --- 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 38da6ecf8152..000000000000 --- 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 d4dac1c386ec..000000000000 --- 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 931822513cc0..000000000000 --- 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 000000000000..bee309f9b811 --- /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 000000000000..1adb58743f72 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs @@ -0,0 +1,40 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_fallback_likelysubtags_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_FALLBACK_LIKELYSUBTAGS_V1: &'static ::Yokeable = &icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1 { + l2s: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"am\0ar\0as\0be\0bg\0bgcbhobn\0brxchrcv\0doiel\0fa\0gu\0he\0hi\0hy\0ja\0ka\0kk\0km\0kn\0ko\0kokks\0ky\0lo\0maimk\0ml\0mn\0mnimr\0my\0ne\0or\0pa\0ps\0rajru\0sa\0satsd\0si\0sr\0ta\0te\0tg\0th\0ti\0tt\0uk\0ur\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"EthiArabBengCyrlCyrlDevaDevaBengDevaCherCyrlDevaGrekArabGujrHebrDevaArmnJpanGeorCyrlKhmrKndaKoreDevaArabCyrlLaooDevaCyrlMlymCyrlBengDevaMymrDevaOryaGuruArabDevaCyrlDevaOlckArabSinhCyrlTamlTeluCyrlThaiEthiCyrlCyrlArabHantHans") }) + }, + lr2s: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0ha\0kk\0ky\0mn\0ms\0pa\0sd\0sr\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x03\0\0\0\x05\0\0\0\t\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x0F\0\0\0\x13\0\0\0\x14\0\0\0\x16\0\0\0\x17\0\0\0&\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IQ\0IR\0RU\0CM\0SD\0AF\0CN\0IR\0MN\0CN\0TR\0CN\0CC\0PK\0IN\0ME\0RO\0RU\0TR\0PK\0AF\0CN\0CN\0AU\0BN\0GB\0GF\0HK\0ID\0MO\0PA\0PF\0PH\0SR\0TH\0TW\0US\0VN\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabArabCyrlArabArabArabArabArabArabArabLatnMongArabArabDevaLatnLatnLatnLatnArabArabCyrlHansHantHantHantHantHantHantHantHantHantHantHantHantHantHantHant") }) + }, + l2r: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"af\0am\0ar\0as\0astaz\0be\0bg\0bgcbhobn\0br\0brxbs\0ca\0cebchrcs\0cv\0cy\0da\0de\0doidsbel\0en\0es\0et\0eu\0fa\0ff\0fi\0filfo\0fr\0ga\0gd\0gl\0gu\0ha\0he\0hi\0hr\0hsbhu\0hy\0ia\0id\0ig\0is\0it\0ja\0jv\0ka\0keakgpkk\0km\0kn\0ko\0kokks\0ky\0lo\0lt\0lv\0maimi\0mk\0ml\0mn\0mnimr\0ms\0my\0ne\0nl\0nn\0no\0or\0pa\0pcmpl\0ps\0pt\0qu\0rajrm\0ro\0ru\0sa\0satsc\0sd\0si\0sk\0sl\0so\0sq\0sr\0su\0sv\0sw\0ta\0te\0tg\0th\0ti\0tk\0to\0tr\0tt\0uk\0ur\0uz\0vi\0wo\0xh\0yo\0yrlyuezh\0zu\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ZA\0ET\0EG\0IN\0ES\0AZ\0BY\0BG\0IN\0IN\0BD\0FR\0IN\0BA\0ES\0PH\0US\0CZ\0RU\0GB\0DK\0DE\0IN\0DE\0GR\0US\0ES\0EE\0ES\0IR\0SN\0FI\0PH\0FO\0FR\0IE\0GB\0ES\0IN\0NG\0IL\0IN\0HR\0DE\0HU\0AM\x00001ID\0NG\0IS\0IT\0JP\0ID\0GE\0CV\0BR\0KZ\0KH\0IN\0KR\0IN\0IN\0KG\0LA\0LT\0LV\0IN\0NZ\0MK\0IN\0MN\0IN\0IN\0MY\0MM\0NP\0NL\0NO\0NO\0IN\0IN\0NG\0PL\0AF\0BR\0PE\0IN\0CH\0RO\0RU\0IN\0IN\0IT\0PK\0LK\0SK\0SI\0SO\0AL\0RS\0ID\0SE\0TZ\0IN\0IN\0TJ\0TH\0ET\0TM\0TO\0TR\0RU\0UA\0PK\0UZ\0VN\0SN\0ZA\0NG\0BR\0HK\0CN\0ZA\0") }) + }, + ls2r: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0en\0ff\0kk\0ky\0mn\0pa\0sd\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x01\0\0\0\x02\0\0\0\x03\0\0\0\x04\0\0\0\x06\0\0\0\x07\0\0\0\x08\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x11\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabShawAdlmArabArabLatnMongArabDevaKhojSindArabArabHansBopoHanbHant") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IR\0GB\0GN\0CN\0CN\0TR\0CN\0PK\0IN\0IN\0IN\0PK\0AF\0CN\0TW\0TW\0TW\0") }) + }, + }; + } + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_LIKELYSUBTAGS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs new file mode 100644 index 000000000000..6f8d6590b085 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs @@ -0,0 +1,28 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_fallback_parents_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_FALLBACK_PARENTS_V1: &'static ::Yokeable = &icu_locid_transform::provider::LocaleFallbackParentsV1 { + parents: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x84\0\0\0\0\0\x06\0\x0B\0\x10\0\x15\0\x1A\0\x1F\0$\0)\0.\x003\08\0=\0B\0G\0L\0Q\0V\0[\0`\0e\0j\0o\0t\0y\0~\0\x83\0\x88\0\x8D\0\x92\0\x97\0\x9C\0\xA1\0\xA6\0\xAB\0\xB0\0\xB5\0\xBA\0\xBF\0\xC4\0\xC9\0\xCE\0\xD3\0\xD8\0\xDD\0\xE2\0\xE7\0\xEC\0\xF1\0\xF6\0\xFB\0\0\x01\x05\x01\n\x01\x0F\x01\x14\x01\x19\x01\x1E\x01#\x01(\x01-\x012\x017\x01<\x01A\x01F\x01K\x01P\x01U\x01Z\x01_\x01d\x01i\x01n\x01s\x01x\x01}\x01\x82\x01\x87\x01\x8C\x01\x91\x01\x96\x01\x9B\x01\xA0\x01\xA5\x01\xAA\x01\xAF\x01\xB4\x01\xB9\x01\xBE\x01\xC3\x01\xC8\x01\xCD\x01\xD2\x01\xD7\x01\xDC\x01\xE1\x01\xE6\x01\xEB\x01\xF0\x01\xF5\x01\xFA\x01\xFF\x01\x04\x02\t\x02\x0E\x02\x13\x02\x18\x02\x1D\x02\"\x02'\x02,\x021\x026\x02;\x02@\x02G\x02I\x02K\x02M\x02R\x02W\x02\\\x02a\x02f\x02k\x02p\x02u\x02z\x02\x7F\x02\x84\x02\x89\x02en-150en-AGen-AIen-ATen-AUen-BBen-BEen-BMen-BSen-BWen-BZen-CCen-CHen-CKen-CMen-CXen-CYen-DEen-DGen-DKen-DMen-ERen-FIen-FJen-FKen-FMen-GBen-GDen-GGen-GHen-GIen-GMen-GYen-HKen-IEen-ILen-IMen-INen-IOen-JEen-JMen-KEen-KIen-KNen-KYen-LCen-LRen-LSen-MGen-MOen-MSen-MTen-MUen-MVen-MWen-MYen-NAen-NFen-NGen-NLen-NRen-NUen-NZen-PGen-PKen-PNen-PWen-RWen-SBen-SCen-SDen-SEen-SGen-SHen-SIen-SLen-SSen-SXen-SZen-TCen-TKen-TOen-TTen-TVen-TZen-UGen-VCen-VGen-VUen-WSen-ZAen-ZMen-ZWes-ARes-BOes-BRes-BZes-CLes-COes-CRes-CUes-DOes-ECes-GTes-HNes-MXes-NIes-PAes-PEes-PRes-PYes-SVes-USes-UYes-VEhi-Latnhtnbnnno-NOpt-AOpt-CHpt-CVpt-FRpt-GQpt-GWpt-LUpt-MOpt-MZpt-STpt-TLzh-Hant-MO") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419en\0\0\0\0\0\0\x01IN\0fr\0\0\0\0\0\0\x01HT\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0zh\0\x01Hant\x01HK\0") }) + }, + }; + } + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_PARENTS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs new file mode 100644 index 000000000000..02eec37ee09f --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs @@ -0,0 +1,32 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_fallback_supplement_co_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl $provider { + #[doc(hidden)] + pub const SINGLETON_FALLBACK_SUPPLEMENT_CO_V1: &'static ::Yokeable = &icu_locid_transform::provider::LocaleFallbackSupplementV1 { + parents: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x01\0\0\0\0\0yue") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"zh\0\x01Hant\0\0\0\0") }) + }, + unicode_extension_defaults: unsafe { + #[allow(unused_unsafe)] + zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"co") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x02\0\0\0") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x02\0zhzh-Hant") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x06\0pinyinstroke") }) + }, + }; + } + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_SUPPLEMENT_CO_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs new file mode 100644 index 000000000000..186f706cdb28 --- /dev/null +++ b/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs @@ -0,0 +1,35 @@ +// @generated +/// Implement `DataProvider` on the given struct using the data +/// hardcoded in this file. This allows the struct to be used with +/// `icu`'s `_unstable` constructors. +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_list_and_v1 { + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO; + #[clippy::msrv = "1.66"] + impl icu_provider::DataProvider for $provider { + fn load(&self, req: icu_provider::DataRequest) -> Result, icu_provider::DataError> { + static EN_001: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static EN_IN: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static IT: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }]); + static PT: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static FR: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static TR: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static ES: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }]); + static RU: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static UND: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static EN: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", & ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" & ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]); + static HI_LATN: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }]); + static JA: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]); + static ZH_HK: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }]); + static ZH: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]); + static ZH_HANT: ::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }]); + static VALUES: [&::Yokeable; 215usize] = [&EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_IN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &HI_LATN, &IT, &IT, &IT, &IT, &JA, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &RU, &RU, &RU, &RU, &RU, &RU, &TR, &TR, &UND, &ZH, &ZH_HK, &ZH, &ZH, &ZH, &ZH_HANT, &ZH_HK, &ZH]; + static KEYS: [&str; 215usize] = ["en", "en-001", "en-150", "en-AE", "en-AG", "en-AI", "en-AS", "en-AT", "en-AU", "en-BB", "en-BE", "en-BI", "en-BM", "en-BS", "en-BW", "en-BZ", "en-CA", "en-CC", "en-CH", "en-CK", "en-CM", "en-CX", "en-CY", "en-DE", "en-DG", "en-DK", "en-DM", "en-ER", "en-FI", "en-FJ", "en-FK", "en-FM", "en-GB", "en-GD", "en-GG", "en-GH", "en-GI", "en-GM", "en-GU", "en-GY", "en-HK", "en-IE", "en-IL", "en-IM", "en-IN", "en-IO", "en-JE", "en-JM", "en-KE", "en-KI", "en-KN", "en-KY", "en-LC", "en-LR", "en-LS", "en-MG", "en-MH", "en-MO", "en-MP", "en-MS", "en-MT", "en-MU", "en-MV", "en-MW", "en-MY", "en-NA", "en-NF", "en-NG", "en-NL", "en-NR", "en-NU", "en-NZ", "en-PG", "en-PH", "en-PK", "en-PN", "en-PR", "en-PW", "en-RW", "en-SB", "en-SC", "en-SD", "en-SE", "en-SG", "en-SH", "en-SI", "en-SL", "en-SS", "en-SX", "en-SZ", "en-TC", "en-TK", "en-TO", "en-TT", "en-TV", "en-TZ", "en-UG", "en-UM", "en-VC", "en-VG", "en-VI", "en-VU", "en-WS", "en-ZA", "en-ZM", "en-ZW", "es", "es-419", "es-AR", "es-BO", "es-BR", "es-BZ", "es-CL", "es-CO", "es-CR", "es-CU", "es-DO", "es-EA", "es-EC", "es-GQ", "es-GT", "es-HN", "es-IC", "es-MX", "es-NI", "es-PA", "es-PE", "es-PH", "es-PR", "es-PY", "es-SV", "es-US", "es-UY", "es-VE", "fr", "fr-BE", "fr-BF", "fr-BI", "fr-BJ", "fr-BL", "fr-CA", "fr-CD", "fr-CF", "fr-CG", "fr-CH", "fr-CI", "fr-CM", "fr-DJ", "fr-DZ", "fr-GA", "fr-GF", "fr-GN", "fr-GP", "fr-GQ", "fr-HT", "fr-KM", "fr-LU", "fr-MA", "fr-MC", "fr-MF", "fr-MG", "fr-ML", "fr-MQ", "fr-MR", "fr-MU", "fr-NC", "fr-NE", "fr-PF", "fr-PM", "fr-RE", "fr-RW", "fr-SC", "fr-SN", "fr-SY", "fr-TD", "fr-TG", "fr-TN", "fr-VU", "fr-WF", "fr-YT", "hi-Latn", "it", "it-CH", "it-SM", "it-VA", "ja", "pt", "pt-AO", "pt-CH", "pt-CV", "pt-GQ", "pt-GW", "pt-LU", "pt-MO", "pt-MZ", "pt-PT", "pt-ST", "pt-TL", "ru", "ru-BY", "ru-KG", "ru-KZ", "ru-MD", "ru-UA", "tr", "tr-CY", "und", "zh", "zh-HK", "zh-Hans", "zh-Hans-HK", "zh-Hans-MO", "zh-Hant", "zh-MO", "zh-SG"]; + if let Ok(payload) = KEYS.binary_search_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).map(|i| *unsafe { VALUES.get_unchecked(i) }) { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(payload)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::MissingLocale.with_req(::KEY, req)) } + } + } + }; +} diff --git a/compiler/rustc_baked_icu_data/src/data/mod.rs b/compiler/rustc_baked_icu_data/src/data/mod.rs index 943187808b81..465689f0cb8d 100644 --- a/compiler/rustc_baked_icu_data/src/data/mod.rs +++ b/compiler/rustc_baked_icu_data/src/data/mod.rs @@ -1,122 +1,31 @@ // @generated -#[clippy::msrv = "1.61"] -mod fallback; -#[clippy::msrv = "1.61"] -mod list; -#[clippy::msrv = "1.61"] -use icu_provider::prelude::*; -/// Implement [`DataProvider`] on the given struct using the data -/// hardcoded in this module. This allows the struct to be used with -/// `icu`'s `_unstable` constructors. -/// -/// This macro can only be called from its definition-site, i.e. right -/// after `include!`-ing the generated module. -/// -/// ```compile_fail -/// struct MyDataProvider; -/// include!("/path/to/generated/mod.rs"); -/// impl_data_provider(MyDataProvider); -/// ``` -#[allow(unused_macros)] +include!("macros.rs"); macro_rules! impl_data_provider { - ($ provider : path) => { - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_list::provider::AndListV1Marker> for $provider { - fn load(&self, req: DataRequest) -> Result, DataError> { - list::and_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| DataErrorKind::MissingLocale.with_req(::icu_list::provider::AndListV1Marker::KEY, req)) - } - } - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker> for $provider { - fn load( - &self, - req: DataRequest, - ) -> Result, DataError> { - fallback::supplement::co_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| { - DataErrorKind::MissingLocale - .with_req(::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY, req) - }) - } - } - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker> for $provider { - fn load( - &self, - req: DataRequest, - ) -> Result, DataError> { - fallback::likelysubtags_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| { - DataErrorKind::MissingLocale - .with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY, req) - }) - } - } - #[clippy::msrv = "1.61"] - impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker> for $provider { - fn load( - &self, - req: DataRequest, - ) -> Result, DataError> { - fallback::parents_v1::lookup(&req.locale) - .map(zerofrom::ZeroFrom::zero_from) - .map(DataPayload::from_owned) - .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) }) - .ok_or_else(|| { - DataErrorKind::MissingLocale.with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY, req) - }) - } - } + ($ provider : ty) => { + make_provider!($provider); + impl_fallback_likelysubtags_v1!($provider); + impl_fallback_parents_v1!($provider); + impl_fallback_supplement_co_v1!($provider); + impl_list_and_v1!($provider); }; } -/// Implement [`AnyProvider`] on the given struct using the data -/// hardcoded in this module. This allows the struct to be used with -/// `icu`'s `_any` constructors. -/// -/// This macro can only be called from its definition-site, i.e. right -/// after `include!`-ing the generated module. -/// -/// ```compile_fail -/// struct MyAnyProvider; -/// include!("/path/to/generated/mod.rs"); -/// impl_any_provider(MyAnyProvider); -/// ``` #[allow(unused_macros)] macro_rules! impl_any_provider { - ($ provider : path) => { - #[clippy::msrv = "1.61"] - impl AnyProvider for $provider { - fn load_any(&self, key: DataKey, req: DataRequest) -> Result { - const ANDLISTV1MARKER: ::icu_provider::DataKeyHash = ::icu_list::provider::AndListV1Marker::KEY.hashed(); - const COLLATIONFALLBACKSUPPLEMENTV1MARKER: ::icu_provider::DataKeyHash = - ::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY.hashed(); - const LOCALEFALLBACKLIKELYSUBTAGSV1MARKER: ::icu_provider::DataKeyHash = - ::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY.hashed(); - const LOCALEFALLBACKPARENTSV1MARKER: ::icu_provider::DataKeyHash = - ::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY.hashed(); + ($ provider : ty) => { + #[clippy::msrv = "1.66"] + impl icu_provider::AnyProvider for $provider { + fn load_any(&self, key: icu_provider::DataKey, req: icu_provider::DataRequest) -> Result { match key.hashed() { - ANDLISTV1MARKER => list::and_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - COLLATIONFALLBACKSUPPLEMENTV1MARKER => fallback::supplement::co_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - LOCALEFALLBACKLIKELYSUBTAGSV1MARKER => fallback::likelysubtags_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - LOCALEFALLBACKPARENTSV1MARKER => fallback::parents_v1::lookup(&req.locale).map(AnyPayload::from_static_ref), - _ => return Err(DataErrorKind::MissingDataKey.with_req(key, req)), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + h if h == ::KEY.hashed() => icu_provider::DataProvider::::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response), + _ => Err(icu_provider::DataErrorKind::MissingDataKey.with_req(key, req)), } - .map(|payload| AnyResponse { payload: Some(payload), metadata: Default::default() }) - .ok_or_else(|| DataErrorKind::MissingLocale.with_req(key, req)) } } }; } -#[clippy::msrv = "1.61"] +#[clippy::msrv = "1.66"] pub struct BakedDataProvider; impl_data_provider!(BakedDataProvider); diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 0b44beeb004c..5248a649c349 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 16814950b0d9..8676d2ba7c4c 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 201f0df12387..d0cf339e7ba4 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -49,7 +49,7 @@ pub fn categorize(context: PlaceContext) -> Option { // cross suspension points so this behavior is unproblematic. PlaceContext::MutatingUse(MutatingUseContext::Borrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) | - PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::FakeBorrow) | // `PlaceMention` and `AscribeUserType` both evaluate the place, which must not // contain dangling references. diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 247200dcd269..9a8f1c97edf4 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 4b95b4783eb4..c85b2f0a9d75 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 695ac6980cd7..41d6b98d7cfa 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 d38cfbc54d7a..9d6b0a0e91ba 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 7b5b52e39b12..ec6d7b74e61a 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 1a74582389d1..5787ea13e793 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 539d0837659c..777ebf0d438d 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 05c2cbd49692..b1f91a056282 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 ec0131c5349a..a31d39e14cd2 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 d053d0a4b3ba..28cc8be8ac95 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 9f30d9d8ba12..bd01210544fa 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 c1f82e19c02e..ee0bd13109bb 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -107,12 +107,12 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> fn next_existential_region_var( &mut self, from_forall: bool, - _name: Option, + name: Option, ) -> ty::Region<'tcx> { let origin = NllRegionVariableOrigin::Existential { from_forall }; let reg_var = - self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(_name)); + self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(name)); reg_var } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 7897a5a63ba8..ae7f9c5244c3 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 809f9838d20b..30c9b35bbacd 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 92da0c069e51..8c2fa6ee95f3 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 5664cbe7d4fa..1a2b2bbc5881 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 1e24d1b113fe..10736ff9a55c 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 7ff805e58d96..2ccdc7d78748 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 000000000000..bad26947967d --- /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 9902bca8eab2..8a690bada0df 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 7e3eaacf8ef0..b832b06e0ffb 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 a299b6de6b1c..cdc78adcf85e 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 331649b2ec24..ce0eecca8a8b 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>, }, 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 c16947609980..e9b7daf14924 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 0c211a06dc4a..ee098be1fce6 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 ea5997a14bb7..4c536048626e 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); + } - 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))); + "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); + + // 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 83d5d53624eb..bfeeb117ff5b 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 5f0aa6c5581d..21ad2a835fc9 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 a530fc994a22..40373ee1d271 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 c0cfe39f1e0a..7a86ddc7556a 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 d5778757caae..0c9f7f195519 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 73821b1685df..307c1264dc1b 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 665d195790c2..10ca5ad802a0 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 a038b3af03dd..7fc02a95be0a 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 7c8ef67ffd10..c86bf81fc131 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 { 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( 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 53cc063e55a5..ed859cb20de9 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 9c053338c853..d802816bb756 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -19,141 +19,183 @@ use rustc_span::Span; /// Features that control behaviour of rustc, rather than the codegen. pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"]; +/// Stability information for target features. +#[derive(Debug, Clone, Copy)] +pub enum Stability { + /// This target feature is stable, it can be used in `#[target_feature]` and + /// `#[cfg(target_feature)]`. + Stable, + /// This target feature is unstable; using it in `#[target_feature]` or `#[cfg(target_feature)]` + /// requires enabling the given nightly feature. + Unstable(Symbol), +} +use Stability::*; + +impl Stability { + fn as_feature_name(self) -> Option { + match self { + Stable => None, + Unstable(s) => Some(s), + } + } + + pub fn is_stable(self) -> bool { + matches!(self, Stable) + } +} + +// Here we list target features that rustc "understands": they can be used in `#[target_feature]` +// and `#[cfg(target_feature)]`. They also do not trigger any warnings when used with +// `-Ctarget-feature`. +// // When adding features to the below lists // check whether they're named already elsewhere in rust // e.g. in stdarch and whether the given name matches LLVM's -// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted +// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted. +// +// Also note that all target features listed here must be purely additive: for target_feature 1.1 to +// be sound, we can never allow features like `+soft-float` (on x86) to be controlled on a +// per-function level, since we would then allow safe calls from functions with `+soft-float` to +// functions without that feature! +// +// When adding a new feature, be particularly mindful of features that affect function ABIs. Those +// need to be treated very carefully to avoid introducing unsoundness! This often affects features +// that enable/disable hardfloat support (see https://github.com/rust-lang/rust/issues/116344 for an +// example of this going wrong), but features enabling new SIMD registers are also a concern (see +// https://github.com/rust-lang/rust/issues/116558 for an example of this going wrong). +// +// Stabilizing a target feature requires t-lang approval. -const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const ARM_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("aclass", Some(sym::arm_target_feature)), - ("aes", Some(sym::arm_target_feature)), - ("crc", Some(sym::arm_target_feature)), - ("d32", Some(sym::arm_target_feature)), - ("dotprod", Some(sym::arm_target_feature)), - ("dsp", Some(sym::arm_target_feature)), - ("fp-armv8", Some(sym::arm_target_feature)), - ("i8mm", Some(sym::arm_target_feature)), - ("mclass", Some(sym::arm_target_feature)), - ("neon", Some(sym::arm_target_feature)), - ("rclass", Some(sym::arm_target_feature)), - ("sha2", Some(sym::arm_target_feature)), + ("aclass", Unstable(sym::arm_target_feature)), + ("aes", Unstable(sym::arm_target_feature)), + ("crc", Unstable(sym::arm_target_feature)), + ("d32", Unstable(sym::arm_target_feature)), + ("dotprod", Unstable(sym::arm_target_feature)), + ("dsp", Unstable(sym::arm_target_feature)), + ("fp-armv8", Unstable(sym::arm_target_feature)), + ("i8mm", Unstable(sym::arm_target_feature)), + ("mclass", Unstable(sym::arm_target_feature)), + ("neon", Unstable(sym::arm_target_feature)), + ("rclass", Unstable(sym::arm_target_feature)), + ("sha2", Unstable(sym::arm_target_feature)), // This is needed for inline assembly, but shouldn't be stabilized as-is // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. - ("thumb-mode", Some(sym::arm_target_feature)), - ("thumb2", Some(sym::arm_target_feature)), - ("trustzone", Some(sym::arm_target_feature)), - ("v5te", Some(sym::arm_target_feature)), - ("v6", Some(sym::arm_target_feature)), - ("v6k", Some(sym::arm_target_feature)), - ("v6t2", Some(sym::arm_target_feature)), - ("v7", Some(sym::arm_target_feature)), - ("v8", Some(sym::arm_target_feature)), - ("vfp2", Some(sym::arm_target_feature)), - ("vfp3", Some(sym::arm_target_feature)), - ("vfp4", Some(sym::arm_target_feature)), - ("virtualization", Some(sym::arm_target_feature)), + ("thumb-mode", Unstable(sym::arm_target_feature)), + ("thumb2", Unstable(sym::arm_target_feature)), + ("trustzone", Unstable(sym::arm_target_feature)), + ("v5te", Unstable(sym::arm_target_feature)), + ("v6", Unstable(sym::arm_target_feature)), + ("v6k", Unstable(sym::arm_target_feature)), + ("v6t2", Unstable(sym::arm_target_feature)), + ("v7", Unstable(sym::arm_target_feature)), + ("v8", Unstable(sym::arm_target_feature)), + ("vfp2", Unstable(sym::arm_target_feature)), + ("vfp3", Unstable(sym::arm_target_feature)), + ("vfp4", Unstable(sym::arm_target_feature)), + ("virtualization", Unstable(sym::arm_target_feature)), // tidy-alphabetical-end ]; -const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start // FEAT_AES - ("aes", None), + ("aes", Stable), // FEAT_BF16 - ("bf16", None), + ("bf16", Stable), // FEAT_BTI - ("bti", None), + ("bti", Stable), // FEAT_CRC - ("crc", None), + ("crc", Stable), // FEAT_DIT - ("dit", None), + ("dit", Stable), // FEAT_DotProd - ("dotprod", None), + ("dotprod", Stable), // FEAT_DPB - ("dpb", None), + ("dpb", Stable), // FEAT_DPB2 - ("dpb2", None), + ("dpb2", Stable), // FEAT_F32MM - ("f32mm", None), + ("f32mm", Stable), // FEAT_F64MM - ("f64mm", None), + ("f64mm", Stable), // FEAT_FCMA - ("fcma", None), + ("fcma", Stable), // FEAT_FHM - ("fhm", None), + ("fhm", Stable), // FEAT_FLAGM - ("flagm", None), + ("flagm", Stable), // FEAT_FP16 - ("fp16", None), + ("fp16", Stable), // FEAT_FRINTTS - ("frintts", None), + ("frintts", Stable), // FEAT_I8MM - ("i8mm", None), + ("i8mm", Stable), // FEAT_JSCVT - ("jsconv", None), + ("jsconv", Stable), // FEAT_LOR - ("lor", None), + ("lor", Stable), // FEAT_LSE - ("lse", None), + ("lse", Stable), // FEAT_MTE - ("mte", None), + ("mte", Stable), // FEAT_AdvSimd & FEAT_FP - ("neon", None), + ("neon", Stable), // FEAT_PAUTH (address authentication) - ("paca", None), + ("paca", Stable), // FEAT_PAUTH (generic authentication) - ("pacg", None), + ("pacg", Stable), // FEAT_PAN - ("pan", None), + ("pan", Stable), // FEAT_PMUv3 - ("pmuv3", None), + ("pmuv3", Stable), // FEAT_RAND - ("rand", None), + ("rand", Stable), // FEAT_RAS - ("ras", None), + ("ras", Stable), // FEAT_RCPC - ("rcpc", None), + ("rcpc", Stable), // FEAT_RCPC2 - ("rcpc2", None), + ("rcpc2", Stable), // FEAT_RDM - ("rdm", None), + ("rdm", Stable), // FEAT_SB - ("sb", None), + ("sb", Stable), // FEAT_SHA1 & FEAT_SHA256 - ("sha2", None), + ("sha2", Stable), // FEAT_SHA512 & FEAT_SHA3 - ("sha3", None), + ("sha3", Stable), // FEAT_SM3 & FEAT_SM4 - ("sm4", None), + ("sm4", Stable), // FEAT_SPE - ("spe", None), + ("spe", Stable), // FEAT_SSBS - ("ssbs", None), + ("ssbs", Stable), // FEAT_SVE - ("sve", None), + ("sve", Stable), // FEAT_SVE2 - ("sve2", None), + ("sve2", Stable), // FEAT_SVE2_AES - ("sve2-aes", None), + ("sve2-aes", Stable), // FEAT_SVE2_BitPerm - ("sve2-bitperm", None), + ("sve2-bitperm", Stable), // FEAT_SVE2_SHA3 - ("sve2-sha3", None), + ("sve2-sha3", Stable), // FEAT_SVE2_SM4 - ("sve2-sm4", None), + ("sve2-sm4", Stable), // FEAT_TME - ("tme", None), - ("v8.1a", Some(sym::aarch64_ver_target_feature)), - ("v8.2a", Some(sym::aarch64_ver_target_feature)), - ("v8.3a", Some(sym::aarch64_ver_target_feature)), - ("v8.4a", Some(sym::aarch64_ver_target_feature)), - ("v8.5a", Some(sym::aarch64_ver_target_feature)), - ("v8.6a", Some(sym::aarch64_ver_target_feature)), - ("v8.7a", Some(sym::aarch64_ver_target_feature)), + ("tme", Stable), + ("v8.1a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.2a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.3a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.4a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.5a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.6a", Unstable(sym::aarch64_ver_target_feature)), + ("v8.7a", Unstable(sym::aarch64_ver_target_feature)), // FEAT_VHE - ("vh", None), + ("vh", Stable), // tidy-alphabetical-end ]; @@ -161,197 +203,197 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[ &["paca", "pacg"], // Together these represent `pauth` in LLVM ]; -const X86_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("adx", None), - ("aes", None), - ("avx", None), - ("avx2", None), - ("avx512bf16", Some(sym::avx512_target_feature)), - ("avx512bitalg", Some(sym::avx512_target_feature)), - ("avx512bw", Some(sym::avx512_target_feature)), - ("avx512cd", Some(sym::avx512_target_feature)), - ("avx512dq", Some(sym::avx512_target_feature)), - ("avx512er", Some(sym::avx512_target_feature)), - ("avx512f", Some(sym::avx512_target_feature)), - ("avx512ifma", Some(sym::avx512_target_feature)), - ("avx512pf", Some(sym::avx512_target_feature)), - ("avx512vbmi", Some(sym::avx512_target_feature)), - ("avx512vbmi2", Some(sym::avx512_target_feature)), - ("avx512vl", Some(sym::avx512_target_feature)), - ("avx512vnni", Some(sym::avx512_target_feature)), - ("avx512vp2intersect", Some(sym::avx512_target_feature)), - ("avx512vpopcntdq", Some(sym::avx512_target_feature)), - ("bmi1", None), - ("bmi2", None), - ("cmpxchg16b", None), - ("ermsb", Some(sym::ermsb_target_feature)), - ("f16c", None), - ("fma", None), - ("fxsr", None), - ("gfni", Some(sym::avx512_target_feature)), - ("lzcnt", None), - ("movbe", None), - ("pclmulqdq", None), - ("popcnt", None), - ("rdrand", None), - ("rdseed", None), - ("rtm", Some(sym::rtm_target_feature)), - ("sha", None), - ("sse", None), - ("sse2", None), - ("sse3", None), - ("sse4.1", None), - ("sse4.2", None), - ("sse4a", Some(sym::sse4a_target_feature)), - ("ssse3", None), - ("tbm", Some(sym::tbm_target_feature)), - ("vaes", Some(sym::avx512_target_feature)), - ("vpclmulqdq", Some(sym::avx512_target_feature)), - ("xsave", None), - ("xsavec", None), - ("xsaveopt", None), - ("xsaves", None), + ("adx", Stable), + ("aes", Stable), + ("avx", Stable), + ("avx2", Stable), + ("avx512bf16", Unstable(sym::avx512_target_feature)), + ("avx512bitalg", Unstable(sym::avx512_target_feature)), + ("avx512bw", Unstable(sym::avx512_target_feature)), + ("avx512cd", Unstable(sym::avx512_target_feature)), + ("avx512dq", Unstable(sym::avx512_target_feature)), + ("avx512er", Unstable(sym::avx512_target_feature)), + ("avx512f", Unstable(sym::avx512_target_feature)), + ("avx512ifma", Unstable(sym::avx512_target_feature)), + ("avx512pf", Unstable(sym::avx512_target_feature)), + ("avx512vbmi", Unstable(sym::avx512_target_feature)), + ("avx512vbmi2", Unstable(sym::avx512_target_feature)), + ("avx512vl", Unstable(sym::avx512_target_feature)), + ("avx512vnni", Unstable(sym::avx512_target_feature)), + ("avx512vp2intersect", Unstable(sym::avx512_target_feature)), + ("avx512vpopcntdq", Unstable(sym::avx512_target_feature)), + ("bmi1", Stable), + ("bmi2", Stable), + ("cmpxchg16b", Stable), + ("ermsb", Unstable(sym::ermsb_target_feature)), + ("f16c", Stable), + ("fma", Stable), + ("fxsr", Stable), + ("gfni", Unstable(sym::avx512_target_feature)), + ("lzcnt", Stable), + ("movbe", Stable), + ("pclmulqdq", Stable), + ("popcnt", Stable), + ("rdrand", Stable), + ("rdseed", Stable), + ("rtm", Unstable(sym::rtm_target_feature)), + ("sha", Stable), + ("sse", Stable), + ("sse2", Stable), + ("sse3", Stable), + ("sse4.1", Stable), + ("sse4.2", Stable), + ("sse4a", Unstable(sym::sse4a_target_feature)), + ("ssse3", Stable), + ("tbm", Unstable(sym::tbm_target_feature)), + ("vaes", Unstable(sym::avx512_target_feature)), + ("vpclmulqdq", Unstable(sym::avx512_target_feature)), + ("xsave", Stable), + ("xsavec", Stable), + ("xsaveopt", Stable), + ("xsaves", Stable), // tidy-alphabetical-end ]; -const HEXAGON_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const HEXAGON_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("hvx", Some(sym::hexagon_target_feature)), - ("hvx-length128b", Some(sym::hexagon_target_feature)), + ("hvx", Unstable(sym::hexagon_target_feature)), + ("hvx-length128b", Unstable(sym::hexagon_target_feature)), // tidy-alphabetical-end ]; -const POWERPC_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const POWERPC_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("altivec", Some(sym::powerpc_target_feature)), - ("power10-vector", Some(sym::powerpc_target_feature)), - ("power8-altivec", Some(sym::powerpc_target_feature)), - ("power8-vector", Some(sym::powerpc_target_feature)), - ("power9-altivec", Some(sym::powerpc_target_feature)), - ("power9-vector", Some(sym::powerpc_target_feature)), - ("vsx", Some(sym::powerpc_target_feature)), + ("altivec", Unstable(sym::powerpc_target_feature)), + ("power10-vector", Unstable(sym::powerpc_target_feature)), + ("power8-altivec", Unstable(sym::powerpc_target_feature)), + ("power8-vector", Unstable(sym::powerpc_target_feature)), + ("power9-altivec", Unstable(sym::powerpc_target_feature)), + ("power9-vector", Unstable(sym::powerpc_target_feature)), + ("vsx", Unstable(sym::powerpc_target_feature)), // tidy-alphabetical-end ]; -const MIPS_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const MIPS_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("fp64", Some(sym::mips_target_feature)), - ("msa", Some(sym::mips_target_feature)), - ("virt", Some(sym::mips_target_feature)), + ("fp64", Unstable(sym::mips_target_feature)), + ("msa", Unstable(sym::mips_target_feature)), + ("virt", Unstable(sym::mips_target_feature)), // tidy-alphabetical-end ]; -const RISCV_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const RISCV_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("a", None), - ("c", None), - ("d", Some(sym::riscv_target_feature)), - ("e", Some(sym::riscv_target_feature)), - ("f", Some(sym::riscv_target_feature)), - ("m", None), - ("relax", Some(sym::riscv_target_feature)), - ("unaligned-scalar-mem", Some(sym::riscv_target_feature)), - ("v", Some(sym::riscv_target_feature)), - ("zba", None), - ("zbb", None), - ("zbc", None), - ("zbkb", None), - ("zbkc", None), - ("zbkx", None), - ("zbs", None), - ("zdinx", Some(sym::riscv_target_feature)), - ("zfh", Some(sym::riscv_target_feature)), - ("zfhmin", Some(sym::riscv_target_feature)), - ("zfinx", Some(sym::riscv_target_feature)), - ("zhinx", Some(sym::riscv_target_feature)), - ("zhinxmin", Some(sym::riscv_target_feature)), - ("zk", None), - ("zkn", None), - ("zknd", None), - ("zkne", None), - ("zknh", None), - ("zkr", None), - ("zks", None), - ("zksed", None), - ("zksh", None), - ("zkt", None), + ("a", Stable), + ("c", Stable), + ("d", Unstable(sym::riscv_target_feature)), + ("e", Unstable(sym::riscv_target_feature)), + ("f", Unstable(sym::riscv_target_feature)), + ("m", Stable), + ("relax", Unstable(sym::riscv_target_feature)), + ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature)), + ("v", Unstable(sym::riscv_target_feature)), + ("zba", Stable), + ("zbb", Stable), + ("zbc", Stable), + ("zbkb", Stable), + ("zbkc", Stable), + ("zbkx", Stable), + ("zbs", Stable), + ("zdinx", Unstable(sym::riscv_target_feature)), + ("zfh", Unstable(sym::riscv_target_feature)), + ("zfhmin", Unstable(sym::riscv_target_feature)), + ("zfinx", Unstable(sym::riscv_target_feature)), + ("zhinx", Unstable(sym::riscv_target_feature)), + ("zhinxmin", Unstable(sym::riscv_target_feature)), + ("zk", Stable), + ("zkn", Stable), + ("zknd", Stable), + ("zkne", Stable), + ("zknh", Stable), + ("zkr", Stable), + ("zks", Stable), + ("zksed", Stable), + ("zksh", Stable), + ("zkt", Stable), // tidy-alphabetical-end ]; -const WASM_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const WASM_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("atomics", Some(sym::wasm_target_feature)), - ("bulk-memory", Some(sym::wasm_target_feature)), - ("exception-handling", Some(sym::wasm_target_feature)), - ("multivalue", Some(sym::wasm_target_feature)), - ("mutable-globals", Some(sym::wasm_target_feature)), - ("nontrapping-fptoint", Some(sym::wasm_target_feature)), - ("reference-types", Some(sym::wasm_target_feature)), - ("relaxed-simd", Some(sym::wasm_target_feature)), - ("sign-ext", Some(sym::wasm_target_feature)), - ("simd128", None), + ("atomics", Unstable(sym::wasm_target_feature)), + ("bulk-memory", Unstable(sym::wasm_target_feature)), + ("exception-handling", Unstable(sym::wasm_target_feature)), + ("multivalue", Unstable(sym::wasm_target_feature)), + ("mutable-globals", Unstable(sym::wasm_target_feature)), + ("nontrapping-fptoint", Unstable(sym::wasm_target_feature)), + ("reference-types", Unstable(sym::wasm_target_feature)), + ("relaxed-simd", Unstable(sym::wasm_target_feature)), + ("sign-ext", Unstable(sym::wasm_target_feature)), + ("simd128", Stable), // tidy-alphabetical-end ]; -const BPF_ALLOWED_FEATURES: &[(&str, Option)] = &[("alu32", Some(sym::bpf_target_feature))]; +const BPF_ALLOWED_FEATURES: &[(&str, Stability)] = &[("alu32", Unstable(sym::bpf_target_feature))]; -const CSKY_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const CSKY_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("10e60", Some(sym::csky_target_feature)), - ("2e3", Some(sym::csky_target_feature)), - ("3e3r1", Some(sym::csky_target_feature)), - ("3e3r2", Some(sym::csky_target_feature)), - ("3e3r3", Some(sym::csky_target_feature)), - ("3e7", Some(sym::csky_target_feature)), - ("7e10", Some(sym::csky_target_feature)), - ("cache", Some(sym::csky_target_feature)), - ("doloop", Some(sym::csky_target_feature)), - ("dsp1e2", Some(sym::csky_target_feature)), - ("dspe60", Some(sym::csky_target_feature)), - ("e1", Some(sym::csky_target_feature)), - ("e2", Some(sym::csky_target_feature)), - ("edsp", Some(sym::csky_target_feature)), - ("elrw", Some(sym::csky_target_feature)), - ("float1e2", Some(sym::csky_target_feature)), - ("float1e3", Some(sym::csky_target_feature)), - ("float3e4", Some(sym::csky_target_feature)), - ("float7e60", Some(sym::csky_target_feature)), - ("floate1", Some(sym::csky_target_feature)), - ("hard-tp", Some(sym::csky_target_feature)), - ("high-registers", Some(sym::csky_target_feature)), - ("hwdiv", Some(sym::csky_target_feature)), - ("mp", Some(sym::csky_target_feature)), - ("mp1e2", Some(sym::csky_target_feature)), - ("nvic", Some(sym::csky_target_feature)), - ("trust", Some(sym::csky_target_feature)), - ("vdsp2e60f", Some(sym::csky_target_feature)), - ("vdspv1", Some(sym::csky_target_feature)), - ("vdspv2", Some(sym::csky_target_feature)), + ("10e60", Unstable(sym::csky_target_feature)), + ("2e3", Unstable(sym::csky_target_feature)), + ("3e3r1", Unstable(sym::csky_target_feature)), + ("3e3r2", Unstable(sym::csky_target_feature)), + ("3e3r3", Unstable(sym::csky_target_feature)), + ("3e7", Unstable(sym::csky_target_feature)), + ("7e10", Unstable(sym::csky_target_feature)), + ("cache", Unstable(sym::csky_target_feature)), + ("doloop", Unstable(sym::csky_target_feature)), + ("dsp1e2", Unstable(sym::csky_target_feature)), + ("dspe60", Unstable(sym::csky_target_feature)), + ("e1", Unstable(sym::csky_target_feature)), + ("e2", Unstable(sym::csky_target_feature)), + ("edsp", Unstable(sym::csky_target_feature)), + ("elrw", Unstable(sym::csky_target_feature)), + ("float1e2", Unstable(sym::csky_target_feature)), + ("float1e3", Unstable(sym::csky_target_feature)), + ("float3e4", Unstable(sym::csky_target_feature)), + ("float7e60", Unstable(sym::csky_target_feature)), + ("floate1", Unstable(sym::csky_target_feature)), + ("hard-tp", Unstable(sym::csky_target_feature)), + ("high-registers", Unstable(sym::csky_target_feature)), + ("hwdiv", Unstable(sym::csky_target_feature)), + ("mp", Unstable(sym::csky_target_feature)), + ("mp1e2", Unstable(sym::csky_target_feature)), + ("nvic", Unstable(sym::csky_target_feature)), + ("trust", Unstable(sym::csky_target_feature)), + ("vdsp2e60f", Unstable(sym::csky_target_feature)), + ("vdspv1", Unstable(sym::csky_target_feature)), + ("vdspv2", Unstable(sym::csky_target_feature)), // tidy-alphabetical-end //fpu // tidy-alphabetical-start - ("fdivdu", Some(sym::csky_target_feature)), - ("fpuv2_df", Some(sym::csky_target_feature)), - ("fpuv2_sf", Some(sym::csky_target_feature)), - ("fpuv3_df", Some(sym::csky_target_feature)), - ("fpuv3_hf", Some(sym::csky_target_feature)), - ("fpuv3_hi", Some(sym::csky_target_feature)), - ("fpuv3_sf", Some(sym::csky_target_feature)), - ("hard-float", Some(sym::csky_target_feature)), - ("hard-float-abi", Some(sym::csky_target_feature)), + ("fdivdu", Unstable(sym::csky_target_feature)), + ("fpuv2_df", Unstable(sym::csky_target_feature)), + ("fpuv2_sf", Unstable(sym::csky_target_feature)), + ("fpuv3_df", Unstable(sym::csky_target_feature)), + ("fpuv3_hf", Unstable(sym::csky_target_feature)), + ("fpuv3_hi", Unstable(sym::csky_target_feature)), + ("fpuv3_sf", Unstable(sym::csky_target_feature)), + ("hard-float", Unstable(sym::csky_target_feature)), + ("hard-float-abi", Unstable(sym::csky_target_feature)), // tidy-alphabetical-end ]; -const LOONGARCH_ALLOWED_FEATURES: &[(&str, Option)] = &[ +const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - ("d", Some(sym::loongarch_target_feature)), - ("f", Some(sym::loongarch_target_feature)), - ("lasx", Some(sym::loongarch_target_feature)), - ("lbt", Some(sym::loongarch_target_feature)), - ("lsx", Some(sym::loongarch_target_feature)), - ("lvz", Some(sym::loongarch_target_feature)), - ("ual", Some(sym::loongarch_target_feature)), + ("d", Unstable(sym::loongarch_target_feature)), + ("f", Unstable(sym::loongarch_target_feature)), + ("lasx", Unstable(sym::loongarch_target_feature)), + ("lbt", Unstable(sym::loongarch_target_feature)), + ("lsx", Unstable(sym::loongarch_target_feature)), + ("lvz", Unstable(sym::loongarch_target_feature)), + ("ual", Unstable(sym::loongarch_target_feature)), // tidy-alphabetical-end ]; @@ -359,7 +401,7 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Option)] = &[ /// primitives may be documented. /// /// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! -pub fn all_known_features() -> impl Iterator)> { +pub fn all_known_features() -> impl Iterator { std::iter::empty() .chain(ARM_ALLOWED_FEATURES.iter()) .chain(AARCH64_ALLOWED_FEATURES.iter()) @@ -375,7 +417,7 @@ pub fn all_known_features() -> impl Iterator &'static [(&'static str, Option)] { +pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Stability)] { match &*sess.target.arch { "arm" => ARM_ALLOWED_FEATURES, "aarch64" => AARCH64_ALLOWED_FEATURES, @@ -520,11 +562,11 @@ pub(crate) fn provide(providers: &mut Providers) { if tcx.sess.opts.actually_rustdoc { // rustdoc needs to be able to document functions that use all the features, so // whitelist them all - all_known_features().map(|(a, b)| (a.to_string(), b)).collect() + all_known_features().map(|(a, b)| (a.to_string(), b.as_feature_name())).collect() } else { supported_target_features(tcx.sess) .iter() - .map(|&(a, b)| (a.to_string(), b)) + .map(|&(a, b)| (a.to_string(), b.as_feature_name())) .collect() } }, diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index ac8123bc1be9..35744d9a167f 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), ErrorGuaranteed>; - /// This is called on the returned `Box` from `join_codegen` - /// - /// # Panics - /// - /// Panics when the passed `Box` was not returned by `join_codegen`. + /// This is called on the returned `CodegenResults` from `join_codegen` fn link( &self, sess: &Session, diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index bda6a9055038..ed2d81727f73 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 fd1736703743..d9f583c1d1f6 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 135c99fefbc8..76116e339859 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::( &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 a137f84b7382..a23922c778ff 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 059029766387..32af537e271d 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 4d71f7636676..5922922d47b6 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 2701fdbbd77f..8d91c4c43768 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 5d7f385c6e4a..d09c026c4b4e 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -127,6 +127,9 @@ impl Drop for OnDrop { } } +/// This is a marker for a fatal compiler error used with `resume_unwind`. +pub struct FatalErrorMarker; + /// Turns a closure that takes an `&mut Formatter` into something that can be display-formatted. pub fn make_display(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Display { struct Printer { diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index a8c442377fbc..266e54604a6b 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 29516fffd6a6..639f05c9e524 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -79,7 +79,7 @@ impl Sharded { pub fn lock_shard_by_value(&self, _val: &K) -> LockGuard<'_, T> { match self { Self::Single(single) => { - // Syncronization is disabled so use the `lock_assume_no_sync` method optimized + // Synchronization is disabled so use the `lock_assume_no_sync` method optimized // for that case. // SAFETY: We know `is_dyn_thread_safe` was false when creating the lock thus @@ -102,7 +102,7 @@ impl Sharded { pub fn lock_shard_by_index(&self, _i: usize) -> LockGuard<'_, T> { match self { Self::Single(single) => { - // Syncronization is disabled so use the `lock_assume_no_sync` method optimized + // Synchronization is disabled so use the `lock_assume_no_sync` method optimized // for that case. // SAFETY: We know `is_dyn_thread_safe` was false when creating the lock thus @@ -111,7 +111,7 @@ impl Sharded { } #[cfg(parallel_compiler)] Self::Shards(shards) => { - // Syncronization is enabled so use the `lock_assume_sync` method optimized + // Synchronization is enabled so use the `lock_assume_sync` method optimized // for that case. // SAFETY (get_unchecked): The index gets ANDed with the shard mask, ensuring it is diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index f957734b04d9..43221d70e21c 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 339aebbf81aa..040a8aa6b638 100644 --- a/compiler/rustc_data_structures/src/sync/lock.rs +++ b/compiler/rustc_data_structures/src/sync/lock.rs @@ -38,7 +38,7 @@ mod maybe_sync { lock: &'a Lock, marker: PhantomData<&'a mut T>, - /// The syncronization mode of the lock. This is explicitly passed to let LLVM relate it + /// The synchronization mode of the lock. This is explicitly passed to let LLVM relate it /// to the original lock operation. mode: Mode, } @@ -142,7 +142,7 @@ mod maybe_sync { .then(|| LockGuard { lock: self, marker: PhantomData, mode }) } - /// This acquires the lock assuming syncronization is in a specific mode. + /// This acquires the lock assuming synchronization is in a specific mode. /// /// Safety /// This method must only be called with `Mode::Sync` if `might_be_dyn_thread_safe` was diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index 39dddb595691..7783de57fba7 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -3,6 +3,8 @@ #![allow(dead_code)] +use crate::sync::IntoDynSyncSend; +use crate::FatalErrorMarker; use parking_lot::Mutex; use std::any::Any; use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; @@ -18,14 +20,17 @@ pub use enabled::*; /// continuing with unwinding. It's also used for the non-parallel code to ensure error message /// output match the parallel compiler for testing purposes. pub struct ParallelGuard { - panic: Mutex>>, + panic: Mutex>>>, } impl ParallelGuard { pub fn run(&self, f: impl FnOnce() -> R) -> Option { catch_unwind(AssertUnwindSafe(f)) .map_err(|err| { - *self.panic.lock() = Some(err); + let mut panic = self.panic.lock(); + if panic.is_none() || !(*err).is::() { + *panic = Some(IntoDynSyncSend(err)); + } }) .ok() } @@ -37,7 +42,7 @@ impl ParallelGuard { pub fn parallel_guard(f: impl FnOnce(&ParallelGuard) -> R) -> R { let guard = ParallelGuard { panic: Mutex::new(None) }; let ret = f(&guard); - if let Some(panic) = guard.panic.into_inner() { + if let Some(IntoDynSyncSend(panic)) = guard.panic.into_inner() { resume_unwind(panic); } ret @@ -77,12 +82,12 @@ mod disabled { }) } - pub fn try_par_for_each_in( + pub fn try_par_for_each_in( t: T, mut for_each: impl FnMut(T::Item) -> Result<(), E>, ) -> Result<(), E> { parallel_guard(|guard| { - t.into_iter().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>, - E: Copy + Send, + E: Send, >( t: T, for_each: impl Fn(::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 ee4337754a9c..7905a0e3924b 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(""); + 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 8c6fee830130..cc533b9941ab 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 8b4b2dc87fd7..20f51441c291 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0795.md +++ b/compiler/rustc_error_codes/src/error_codes/E0795.md @@ -3,7 +3,7 @@ Invalid argument for the `offset_of!` macro. Erroneous code example: ```compile_fail,E0795 -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] let x = std::mem::offset_of!(Option, Some); ``` @@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option` can be found by specifying the field name `0`: ``` -#![feature(offset_of)] +#![feature(offset_of, offset_of_enum)] let x: usize = std::mem::offset_of!(Option, Some.0); ``` diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 6d95fbcfad00..68dba8602912 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 dd462cc64865..8ae95cbeed26 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 d3a08da62839..67e4963fddf7 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 11782e33d84b..64b5a7d2921a 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 d88f165b9e53..c4e44a6a4e38 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 3e700f2da869..cb9259998e3d 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 2fcb45ef8aa1..5a9c67a6a9d2 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 90babbb63a00..d3a383ff7c55 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 . + 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 c61719c1fd29..eb009b9368f9 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 046983e90f7b..729e9f2f1d17 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> 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 7eeb7837467f..8d87cb57b907 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 6424d1c79311..d51e9eb5983a 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 ca7679cfba06..d5fb4340e1c8 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> 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 a6410c944f77..85703c60c30a 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 5f8b1ace68b7..6c1efb6470e8 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 1ce6bb6ca15f..5f82d9f06c6e 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 b8a265d4971d..1edc3efbc778 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 a70ead8e57d6..7807ff6547d2 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 acaa3e02f092..77d6183f862f 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 a11fe10c01c7..a6f78dc8ab53 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>, - span: Span, - ) { + fn point_at_index(&self, errors: &mut Vec>, span: Span) { + let mut seen_preds = FxHashSet::default(); + // We re-sort here so that the outer most root obligations comes first, as we have the + // subsequent weird logic to identify *every* relevant obligation for proper deduplication + // of diagnostics. + errors.sort_by_key(|error| error.root_obligation.recursion_depth); for error in errors { - match error.obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) - if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) => { + match ( + error.root_obligation.predicate.kind().skip_binder(), + error.obligation.predicate.kind().skip_binder(), + ) { + (ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)), _) + if self.tcx.lang_items().index_trait() == Some(predicate.trait_ref.def_id) => + { + seen_preds.insert(error.obligation.predicate.kind().skip_binder()); } + (_, ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate))) + if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) => + { + seen_preds.insert(error.obligation.predicate.kind().skip_binder()); + } + (root, pred) if seen_preds.contains(&pred) || seen_preds.contains(&root) => {} _ => continue, } error.obligation.cause.span = span; @@ -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 b5a07f0d3e9e..750ed2c34913 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>, &'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 e93d180fc139..a1ce5983f30e 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 c43d4932fb9f..2e0ab1560f4b 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 86a0e95de1da..d69d2529b18d 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 74f469cb39cb..a51fa8354c9e 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 12cc5ed2f1a5..bd40e6c10476 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>, + args: Option<&'tcx [hir::Expr<'tcx>]>, expected: Expectation<'tcx>, trait_missing_method: bool, ) -> Option> { @@ -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>, + 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>, + self_source: SelfSource<'tcx>, + args: Option<&'tcx [hir::Expr<'tcx>]>, span: Span, err: &mut Diagnostic, sources: &mut Vec, @@ -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` or `Result`. + fn find_builder_fn(&self, err: &mut Diagnostic, rcvr_ty: Ty<'tcx>) { + let ty::Adt(adt_def, _) = rcvr_ty.kind() else { + return; + }; + let mut items = self + .tcx + .inherent_impls(adt_def.did()) + .iter() + .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) + // Only assoc fn with no receivers. + .filter(|item| matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter) + .filter_map(|item| { + // Only assoc fns that return `Self`, `Option` or `Result`. + let ret_ty = self.tcx.fn_sig(item.def_id).skip_binder().output(); + let ret_ty = self.tcx.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` or `-> Result` + if ![self.tcx.lang_items().option_type(), self.tcx.get_diagnostic_item(sym::Result)] + .contains(&Some(def.did())) + { + return None; + } + let arg = args.get(0)?.expect_ty(); + if self.can_eq(self.param_env, rcvr_ty, arg) { + Some((item.def_id, ret_ty)) + } else { + None + } + }) + .collect::>(); + let post = if items.len() > 5 { + let items_len = items.len(); + items.truncate(4); + format!("\nand {} others", items_len - 4) + } else { + String::new() + }; + match &items[..] { + [] => {} + [(def_id, ret_ty)] => { + err.span_note( + self.tcx.def_span(def_id), + format!( + "if you're trying to build a new `{rcvr_ty}`, consider using `{}` which \ + returns `{ret_ty}`", + self.tcx.def_path_str(def_id), + ), + ); + } + _ => { + let span: MultiSpan = items + .iter() + .map(|(def_id, _)| self.tcx.def_span(def_id)) + .collect::>() + .into(); + err.span_note( + span, + format!( + "if you're trying to build a new `{rcvr_ty}` consider using one of the \ + following associated functions:\n{}{post}", + items + .iter() + .map(|(def_id, _ret_ty)| self.tcx.def_path_str(def_id)) + .collect::>() + .join("\n") + ), + ); + } + } + } + /// Suggest calling `Ty::method` if `.method()` isn't found because the method /// doesn't take a `self` receiver. fn suggest_associated_call_syntax( @@ -1416,7 +1510,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty: Ty<'tcx>, source: SelfSource<'tcx>, item_name: Ident, - args: Option>, + args: Option<&'tcx [hir::Expr<'tcx>]>, sugg_span: Span, ) { let mut has_unsuggestable_args = false; @@ -1490,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::>() + 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::>() + } 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::>() + .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::>() - .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 { } fn print_disambiguation_help<'tcx>( - item_name: Ident, - args: Option>, + tcx: TyCtxt<'tcx>, err: &mut Diagnostic, - trait_name: String, - rcvr_ty: Ty<'_>, - impl_self_ty: Option>, - kind: ty::AssocKind, - def_kind_descr: &'static str, + source: SelfSource<'tcx>, + args: Option<&'tcx [hir::Expr<'tcx>]>, + trait_ref: ty::TraitRef<'tcx>, + candidate_idx: Option, span: Span, - candidate: Option, - source_map: &source_map::SourceMap, - fn_has_self_parameter: bool, + item: ty::AssocItem, ) -> Option { + let trait_ref = if item.fn_has_self_parameter { + trait_ref.print_only_trait_name().to_string() + } else { + format!("<{} as {}>", trait_ref.args[0], trait_ref.print_only_trait_name()) + }; Some( - if let (ty::AssocKind::Fn, Some(MethodCallComponents { receiver, args, .. })) = (kind, args) + if matches!(item.kind, ty::AssocKind::Fn) + && let SelfSource::MethodCall(receiver) = source + && let Some(args) = args { + let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id); + let item_name = item.ident(tcx); + let rcvr_ref = tcx.fn_sig(item.def_id).skip_binder().skip_binder().inputs()[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::>() .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 d0d3b0e5b73c..f40406c67265 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 50684482c0d5..b30f9b82fbbf 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 75c70ec59fb7..17b81acd506a 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 896aacc69931..2dfe72726734 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -784,7 +784,7 @@ impl<'tcx> TypeFolder> 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> 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 5d885e07192d..e74173b24a97 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 05ed4f7598d4..61bb0353a9f4 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -270,12 +270,6 @@ pub struct LoadDepGraph { pub err: std::io::Error, } -#[derive(Diagnostic)] -#[diag(incremental_decode_incr_cache)] -pub struct DecodeIncrCache { - pub err: String, -} - #[derive(Diagnostic)] #[diag(incremental_write_dep_graph)] pub struct WriteDepGraph<'a> { diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index cbd55fe42056..6dfc40969106 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -30,8 +30,6 @@ pub enum LoadResult { DataOutOfDate, /// Loading the dep graph failed. LoadDepGraph(PathBuf, std::io::Error), - /// Decoding loaded incremental cache failed. - DecodeIncrCache(Box), } impl LoadResult { @@ -44,9 +42,7 @@ impl LoadResult { } ( Some(IncrementalStateAssertion::Loaded), - LoadResult::LoadDepGraph(..) - | LoadResult::DecodeIncrCache(..) - | LoadResult::DataOutOfDate, + LoadResult::LoadDepGraph(..) | LoadResult::DataOutOfDate, ) => { sess.emit_fatal(errors::AssertLoaded); } @@ -58,10 +54,6 @@ impl LoadResult { sess.emit_warning(errors::LoadDepGraph { path, err }); Default::default() } - LoadResult::DecodeIncrCache(err) => { - sess.emit_warning(errors::DecodeIncrCache { err: format!("{err:?}") }); - Default::default() - } LoadResult::DataOutOfDate => { if let Err(err) = delete_all_session_dir_contents(sess) { sess.emit_err(errors::DeleteIncompatible { path: dep_graph_path(sess), err }); @@ -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 ece61ff12520..d0b4889b45fa 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -237,23 +237,12 @@ impl BitSet { new_word != word } - /// Gets a slice of the underlying words. - pub fn words(&self) -> &[Word] { - &self.words - } - /// Iterates over the indices of set bits in a sorted order. #[inline] pub fn iter(&self) -> BitIter<'_, T> { BitIter::new(&self.words) } - /// Duplicates the set as a hybrid set. - pub fn to_hybrid(&self) -> HybridBitSet { - // Note: we currently don't bother trying to make a Sparse set. - HybridBitSet::Dense(self.to_owned()) - } - /// Set `self = self | other`. In contrast to `union` returns `true` if the set contains at /// least one bit that is not in `other` (i.e. `other` is not a superset of `self`). /// @@ -1601,11 +1590,11 @@ impl BitMatrix { pub fn from_row_n(row: &BitSet, num_rows: usize) -> BitMatrix { let num_columns = row.domain_size(); let words_per_row = num_words(num_columns); - assert_eq!(words_per_row, row.words().len()); + assert_eq!(words_per_row, row.words.len()); BitMatrix { num_rows, num_columns, - words: iter::repeat(row.words()).take(num_rows).flatten().cloned().collect(), + words: iter::repeat(&row.words).take(num_rows).flatten().cloned().collect(), marker: PhantomData, } } @@ -1700,9 +1689,9 @@ impl BitMatrix { assert_eq!(with.domain_size(), self.num_columns); let (write_start, write_end) = self.range(write); let mut changed = false; - for (read_index, write_index) in iter::zip(0..with.words().len(), write_start..write_end) { + for (read_index, write_index) in iter::zip(0..with.words.len(), write_start..write_end) { let word = self.words[write_index]; - let new_word = word | with.words()[read_index]; + let new_word = word | with.words[read_index]; self.words[write_index] = new_word; changed |= word != new_word; } @@ -2002,54 +1991,6 @@ impl std::fmt::Debug for FiniteBitSet { } } -impl FiniteBitSetTy for u64 { - const DOMAIN_SIZE: u32 = 64; - - const FILLED: Self = Self::MAX; - const EMPTY: Self = Self::MIN; - - const ONE: Self = 1u64; - const ZERO: Self = 0u64; - - fn checked_shl(self, rhs: u32) -> Option { - self.checked_shl(rhs) - } - - fn checked_shr(self, rhs: u32) -> Option { - self.checked_shr(rhs) - } -} - -impl std::fmt::Debug for FiniteBitSet { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:064b}", self.0) - } -} - -impl FiniteBitSetTy for u128 { - const DOMAIN_SIZE: u32 = 128; - - const FILLED: Self = Self::MAX; - const EMPTY: Self = Self::MIN; - - const ONE: Self = 1u128; - const ZERO: Self = 0u128; - - fn checked_shl(self, rhs: u32) -> Option { - self.checked_shl(rhs) - } - - fn checked_shr(self, rhs: u32) -> Option { - self.checked_shr(rhs) - } -} - -impl std::fmt::Debug for FiniteBitSet { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:0128b}", self.0) - } -} - /// A fixed-sized bitset type represented by an integer type. Indices outwith than the range /// representable by `T` are considered set. #[derive(Copy, Clone, Eq, PartialEq, Decodable, Encodable)] diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 99e72e49f8eb..66c5cc774b22 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -137,10 +137,6 @@ impl IndexVec { self.raw.truncate(a) } - pub fn convert_index_type(self) -> IndexVec { - IndexVec::from_raw(self.raw) - } - /// Grows the index vector so that it contains an entry for /// `elem`; if that is already true, then has no /// effect. Otherwise, inserts new values as needed by invoking diff --git a/compiler/rustc_index/src/vec/tests.rs b/compiler/rustc_index/src/vec/tests.rs index cb0f0db220d9..7e5e41bd2d19 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 57bc14ebcb3f..869878420aeb 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 0e2f9ba70fec..ba7007d908f6 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>, { - 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>, { - 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>, { - 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> 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 ed101082130c..d911e28484c2 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 e4be435fded3..f09a33be839b 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 fe18d00293aa..f0b33d30e2c6 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 35204478c54d..e212547eaafb 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> 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 17fe3aa7b44c..84891022720c 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 bee0a978ad04..4ff9d7494226 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 4ee897ffe984..3c539f18eb92 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( &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>, } @@ -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 7a5dec22fe04..7a792d30cc74 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 { 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 38819e8ad8a6..f867876a2e63 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 398ac94ee368..2db8579af52a 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -37,7 +37,7 @@ where fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { // ignore bound regions, keep visiting - ty::ReLateBound(_, _) => ControlFlow::Continue(()), + ty::ReBound(_, _) => ControlFlow::Continue(()), _ => { (self.op)(r); ControlFlow::Continue(()) 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 6f973ee37f5e..959b34aa1457 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 3fa9a7333a45..de142f05fb76 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 3c566e0dd6da..8cee13ce4ec7 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 8e66083a390f..8a5851bd5cbc 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 d44691b5e9ba..82483ac7dc0f 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 918e484b9f44..bef9f469cc65 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 fe13162cd4a3..ed1e87713237 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 3f2bf2c9b444..142384e6d0ca 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 5e3b91c17bf6..42ca60a6d8ab 100644 --- a/compiler/rustc_macros/src/current_version.rs +++ b/compiler/rustc_macros/src/current_version.rs @@ -1,37 +1,16 @@ use proc_macro::TokenStream; use proc_macro2::Span; use quote::quote; -use syn::parse::{Parse, ParseStream}; -use syn::{parenthesized, parse_macro_input, LitStr, Token}; -pub struct Input { - variable: LitStr, -} - -mod kw { - syn::custom_keyword!(env); -} - -impl Parse for Input { - // Input syntax is `env!("CFG_RELEASE")` to facilitate grepping. - fn parse(input: ParseStream<'_>) -> syn::Result { - let paren; - input.parse::()?; - input.parse::()?; - parenthesized!(paren in input); - let variable: LitStr = paren.parse()?; - Ok(Input { variable }) - } -} - -pub(crate) fn current_version(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as Input); - - TokenStream::from(match RustcVersion::parse_env_var(&input.variable) { +pub(crate) fn current_version(_input: TokenStream) -> TokenStream { + let env_var = "CFG_RELEASE"; + TokenStream::from(match RustcVersion::parse_cfg_release(env_var) { Ok(RustcVersion { major, minor, patch }) => quote!( + // The produced literal has type `rustc_session::RustcVersion`. Self { major: #major, minor: #minor, patch: #patch } ), - Err(err) => syn::Error::new(Span::call_site(), err).into_compile_error(), + Err(err) => syn::Error::new(Span::call_site(), format!("{env_var} env var: {err}")) + .into_compile_error(), }) } @@ -42,8 +21,8 @@ struct RustcVersion { } impl RustcVersion { - fn parse_env_var(env_var: &LitStr) -> Result> { - let value = proc_macro::tracked_env::var(env_var.value())?; + fn parse_cfg_release(env_var: &str) -> Result> { + let value = proc_macro::tracked_env::var(env_var)?; Self::parse_str(&value) .ok_or_else(|| format!("failed to parse rustc version: {:?}", value).into()) } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 1a8174bfd968..31ad9cdb2161 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 e9a5cd9de97b..2755a161d91e 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -53,6 +53,7 @@ pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> { /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that /// has the actual diagnostic message. pub slug: SpannedOption, + /// Error codes are a optional part of the struct attribute - this is only set to detect /// multiple specifications. pub code: SpannedOption<()>, @@ -68,7 +69,7 @@ impl DiagnosticDeriveBuilder { /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions /// or attributes on the type itself when input is an enum. - pub fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream + pub(crate) fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream where F: for<'a, 'v> Fn(DiagnosticDeriveVariantBuilder<'a>, &VariantInfo<'v>) -> TokenStream, { @@ -121,7 +122,7 @@ impl DiagnosticDeriveBuilder { impl<'a> DiagnosticDeriveVariantBuilder<'a> { /// Generates calls to `code` and similar functions based on the attributes on the type or /// variant. - pub fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream { + pub(crate) fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream { let ast = variant.ast(); let attrs = &ast.attrs; let preamble = attrs.iter().map(|attr| { @@ -135,7 +136,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { /// Generates calls to `span_label` and similar functions based on the attributes on fields or /// calls to `set_arg` when no attributes are present. - pub fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream { + pub(crate) fn body(&mut self, variant: &VariantInfo<'_>) -> TokenStream { let mut body = quote! {}; // Generate `set_arg` calls first.. for binding in variant.bindings().iter().filter(|bi| should_generate_set_arg(bi.ast())) { diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 877271ff0774..0f9e68cdc501 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -478,7 +478,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } } - pub fn into_tokens(&mut self) -> Result { + pub(crate) fn into_tokens(&mut self) -> Result { let kind_slugs = self.identify_kind()?; if kind_slugs.is_empty() { if self.is_enum { diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 125632921816..2700f02e33a6 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -17,7 +17,7 @@ use synstructure::{BindingInfo, VariantInfo}; use super::error::invalid_attr; thread_local! { - pub static CODE_IDENT_COUNT: RefCell = RefCell::new(0); + pub(crate) static CODE_IDENT_COUNT: RefCell = RefCell::new(0); } /// Returns an ident of the form `__code_N` where `N` is incremented once with every call. @@ -208,7 +208,7 @@ impl<'ty> FieldInnerTy<'ty> { } } - pub fn span(&self) -> proc_macro2::Span { + pub(crate) fn span(&self) -> proc_macro2::Span { match self { FieldInnerTy::Option(ty) | FieldInnerTy::Vec(ty) | FieldInnerTy::Plain(ty) => ty.span(), } @@ -537,7 +537,7 @@ impl fmt::Display for SuggestionKind { } impl SuggestionKind { - pub fn to_suggestion_style(&self) -> TokenStream { + pub(crate) fn to_suggestion_style(&self) -> TokenStream { match self { SuggestionKind::Normal => { quote! { rustc_errors::SuggestionStyle::ShowCode } diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index 75a2f7009c25..6d23b9ac99d2 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 193dbd75fbd5..a66666360324 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 ba75517d7a66..047066ac6815 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -5,11 +5,16 @@ use syn::spanned::Spanned; pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { let decoder_ty = quote! { __D }; - if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { - s.add_impl_generic(parse_quote! { 'tcx }); - } - s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_type_ir::codec::TyDecoder>}); - s.add_bounds(synstructure::AddBounds::Generics); + let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + quote! { > } + } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") { + quote! { } + } else { + quote! {} + }; + + s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_type_ir::codec::TyDecoder #bound }); + s.add_bounds(synstructure::AddBounds::Fields); decodable_body(s, decoder_ty) } @@ -97,12 +102,17 @@ fn decode_field(field: &syn::Field) -> proc_macro2::TokenStream { } pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { - if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { - s.add_impl_generic(parse_quote! {'tcx}); - } + let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + quote! { > } + } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") { + quote! { } + } else { + quote! {} + }; + let encoder_ty = quote! { __E }; - s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_type_ir::codec::TyEncoder>}); - s.add_bounds(synstructure::AddBounds::Generics); + s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_type_ir::codec::TyEncoder #bound }); + s.add_bounds(synstructure::AddBounds::Fields); encodable_body(s, encoder_ty, false) } diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index 4129712a6b21..3de4a904e5fd 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) { }; (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 ec2517b581e3..b06b4fb87cde 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 de436c16ca92..2042863d189d 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 0b5426c3bb1a..5a957d2c26d6 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 041a63776d11..92d1fcc7ed24 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 { // 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 448a3029ae97..fd29e74e905d 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 7054cede2d87..874c997c23be 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 }, } impl DefLocation { pub fn dominates(self, location: Location, dominators: &Dominators) -> bool { match self { DefLocation::Argument => true, - DefLocation::Body(def) => def.successor_within_block().dominates(location, dominators), + DefLocation::Assignment(def) => { + def.successor_within_block().dominates(location, dominators) + } + DefLocation::CallReturn { target: None, .. } => false, + DefLocation::CallReturn { call, target: Some(target) } => { + // The definition occurs on the call -> target edge. The definition dominates a use + // if and only if the edge is on all paths from the entry to the use. + // + // Note that a call terminator has only one edge that can reach the target, so when + // the call strongly dominates the target, all paths from the entry to the target + // go through the call -> target edge. + call != target + && dominators.dominates(call, target) + && dominators.dominates(target, location.block) + } } } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index debd85dad2e0..a1324858416a 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 0540eb0efd6c..d609965f36fe 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 5864acaed7b2..3471d620ee69 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 b6543affc6db..7b0f27f9b348 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 931ee7fd05ef..6ab2da23a8ad 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 0f0ca3a1420e..d47cfd5712f8 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 e20e9d9312c1..cdde6a596a80 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -2,7 +2,8 @@ use crate::mir; use crate::query::CyclePlaceholder; use crate::traits; use crate::ty::{self, Ty}; -use std::mem::{size_of, transmute_copy, MaybeUninit}; +use std::intrinsics::transmute_unchecked; +use std::mem::{size_of, MaybeUninit}; #[derive(Copy, Clone)] pub struct Erased { @@ -29,8 +30,15 @@ pub fn erase(src: T) -> Erase { }; Erased::<::Result> { + // `transmute_unchecked` is needed here because it does not have `transmute`'s size check + // (and thus allows to transmute between `T` and `MaybeUninit`) (we do the size + // check ourselves in the `const` block above). + // + // `transmute_copy` is also commonly used for this (and it would work here since + // `EraseType: Copy`), but `transmute_unchecked` better explains the intent. + // // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes. - data: unsafe { transmute_copy(&src) }, + data: unsafe { transmute_unchecked::>(src) }, } } @@ -38,22 +46,24 @@ pub fn erase(src: T) -> Erase { #[inline(always)] pub fn restore(value: Erase) -> T { let value: Erased<::Result> = value; + // See comment in `erase` for why we use `transmute_unchecked`. + // // SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of // the right size. - unsafe { transmute_copy(&value.data) } + unsafe { transmute_unchecked::, T>(value.data) } } impl EraseType for &'_ T { - type Result = [u8; size_of::<*const ()>()]; + type Result = [u8; size_of::<&'static ()>()]; } impl EraseType for &'_ [T] { - type Result = [u8; size_of::<*const [()]>()]; + type Result = [u8; size_of::<&'static [()]>()]; } impl EraseType for &'_ ty::List { - type Result = [u8; size_of::<*const ()>()]; + type Result = [u8; size_of::<&'static ty::List<()>>()]; } impl EraseType for &'_ rustc_index::IndexSlice { diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index d03d92c3a4b8..8feefb4c03cc 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 9e2ff3820af6..6cd75e087276 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 cfacccd26799..af5ffc20d489 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 68812bba42fd..1598d05251d4 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>, /// Pre-interned values of the form: - /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` + /// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` /// for small values of `i` and `v`. pub re_late_bounds: Vec>>, } @@ -402,7 +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 77a50fa9276d..0094825fc70d 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 7895993ccffa..cfd36fd8c7c3 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -20,8 +20,8 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - // If there's nothing to erase avoid performing the query at all - if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { + // If there's nothing to erase or anonymize, avoid performing the query at all + if !value.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) { return value; } debug!("erase_regions({:?})", value); @@ -53,16 +53,11 @@ impl<'tcx> TypeFolder> for RegionEraserVisitor<'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - // because late-bound regions affect subtyping, we can't - // erase the bound/free distinction, but we can replace - // all free regions with 'erased. - // - // Note that we *CAN* replace early-bound regions -- the - // type system never "sees" those, they get substituted - // away. In codegen, they will always be erased to 'erased - // whenever a substitution occurs. + // We must not erase bound regions. `for<'a> fn(&'a ())` and + // `fn(&'free ())` are different types: they may implement different + // traits and have a different `TypeId`. match *r { - ty::ReLateBound(..) => r, + ty::ReBound(..) => r, _ => self.tcx.lifetimes.re_erased, } } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 738bb5e8b195..b26f98769c14 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 75ea53195a3a..f95ceeff1507 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 a348e9f608aa..4d7b12662c66 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) -> 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 00529a1e066c..e8ff3b230cbb 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -68,12 +68,10 @@ impl<'tcx> TyCtxt<'tcx> { /// Folds over the substructure of a type, visiting its component /// types and all regions that occur *free* within it. /// -/// That is, `Ty` can contain function or method types that bind -/// regions at the call site (`ReLateBound`), and occurrences of -/// regions (aka "lifetimes") that are bound within a type are not -/// visited by this folder; only regions that occur free will be +/// That is, function pointer types and trait object can introduce +/// new bound regions which are not visited by this visitors as +/// they are not free; only regions that occur free will be /// visited by `fld_r`. - pub struct RegionFolder<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -117,7 +115,7 @@ impl<'a, 'tcx> TypeFolder> for RegionFolder<'a, 'tcx> { #[instrument(skip(self), level = "debug", ret)] fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, _) if debruijn < self.current_index => { + ty::ReBound(debruijn, _) if debruijn < self.current_index => { debug!(?self.current_index, "skipped bound region"); r } @@ -205,15 +203,15 @@ where fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { + ty::ReBound(debruijn, br) if debruijn == self.current_index => { let region = self.delegate.replace_region(br); - if let ty::ReLateBound(debruijn1, br) = *region { - // If the callback returns a late-bound region, + if let ty::ReBound(debruijn1, br) = *region { + // If the callback returns a bound region, // that region should always use the INNERMOST // debruijn index. Then we adjust it to the // correct depth. assert_eq!(debruijn1, ty::INNERMOST); - ty::Region::new_late_bound(self.tcx, debruijn, br) + ty::Region::new_bound(self.tcx, debruijn, br) } else { region } @@ -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> 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 41a1bf04e5f3..c9607b2245a7 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> 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 4223e503f5e2..aca6acd783b9 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 739d4fa886ec..e1c616ba0785 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; +pub type PlaceholderConst = Placeholder; /// 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 8d895732dff2..cabf2ab5dfec 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -102,8 +102,9 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { // Ignore bound regions and `'static` regions that appear in the // type, we only need to remap regions that reference lifetimes // from the function declaration. - // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. - ty::ReLateBound(..) | ty::ReStatic => return r, + // + // E.g. We ignore `'r` in a type like `for<'r> fn(&'r u32)`. + ty::ReBound(..) | ty::ReStatic => return r, // If regions have been erased (by writeback), don't try to unerase // them. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index baf160bcc99d..21bf5b4b3b1b 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> 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> 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 44592b10d557..d0df4498a66e 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 e9240d1b268e..1a76a8d350d2 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 a251518d1457..144e98f784a4 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 ab0999b3f197..f14232d34352 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> { } /// True if there are any late-bound regions - fn has_late_bound_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) + fn has_bound_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_BOUND) } /// True if there are any late-bound non-region variables - fn has_non_region_late_bound(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND) + fn has_non_region_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_BOUND_VARS - TypeFlags::HAS_RE_BOUND) } - /// True if there are any late-bound variables - fn has_late_bound_vars(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_LATE_BOUND) + /// True if there are any bound variables + fn has_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_BOUND_VARS) } /// Indicates whether this value still has parameters/placeholders/inference variables @@ -204,7 +204,7 @@ impl<'tcx> TyCtxt<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { - ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => { + ty::ReBound(debruijn, _) if debruijn < self.outer_index => { ControlFlow::Continue(()) } _ => { @@ -337,7 +337,7 @@ impl<'tcx> TypeVisitor> for ValidateBoundVars<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { - ty::ReLateBound(index, br) if index == self.binder_index => { + ty::ReBound(index, br) if index == self.binder_index => { if self.bound_vars.len() <= br.var.as_usize() { bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars); } @@ -494,15 +494,11 @@ impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { &mut self, t: &Binder<'tcx, T>, ) -> ControlFlow { - // If we're looking for any of the HAS_*_LATE_BOUND flags, we need to - // additionally consider the bound vars on the binder itself, even if - // the contents of a the binder (e.g. a `TraitRef`) doesn't reference - // the bound vars. - if self.flags.intersects(TypeFlags::HAS_LATE_BOUND) { - let bound_var_flags = FlagComputation::bound_var_flags(t.bound_vars()); - if bound_var_flags.flags.intersects(self.flags) { - return ControlFlow::Break(FoundFlags); - } + // If we're looking for the HAS_BINDER_VARS flag, check if the + // binder has vars. This won't be present in the binder's bound + // value, so we need to check here too. + if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() { + return ControlFlow::Break(FoundFlags); } t.super_visit_with(self) @@ -617,7 +613,7 @@ impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - if let ty::ReLateBound(debruijn, br) = *r { + if let ty::ReBound(debruijn, br) = *r { if debruijn == self.current_index { self.regions.insert(br.kind); } diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index f30993c9a694..2b4ae3736269 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -114,12 +114,11 @@ impl<'tcx> Value> for ty::EarlyBinder> } impl<'tcx, T> Value> for Result> { - fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> Self { + fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self { // tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under // min_specialization. Since this is an error path anyways, leaking doesn't matter (and really, // tcx.arena.alloc is pretty much equal to leaking). - // FIXME: `Cycle` should carry the ErrorGuaranteed - Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle))) + Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle(guar)))) } } diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 32711c23dc4e..7dd0e7d4b928 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 3de2f45ad9a8..d302d538ad41 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 = Result; diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index e2ab2cb90c72..a6f9caada2d1 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -27,10 +27,13 @@ macro_rules! parse_by_kind { $expr_name:pat, $expected:literal, $( - @call($name:literal, $args:ident) => $call_expr:expr, + @call($name:ident, $args:ident) => $call_expr:expr, )* $( - $pat:pat => $expr:expr, + @variant($adt:ident, $variant:ident) => $variant_expr:expr, + )* + $( + $pat:pat $(if $guard:expr)? => $expr:expr, )* ) => {{ let expr_id = $self.preparse($expr_id); @@ -42,14 +45,20 @@ macro_rules! parse_by_kind { ExprKind::Call { ty, fun: _, args: $args, .. } if { match ty.kind() { ty::FnDef(did, _) => { - $self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did) + $self.tcx.is_diagnostic_item(rustc_span::sym::$name, *did) } _ => false, } } => $call_expr, )* $( - $pat => $expr, + ExprKind::Adt(box AdtExpr { adt_def, variant_index, .. }) if { + $self.tcx.is_diagnostic_item(rustc_span::sym::$adt, adt_def.did()) && + adt_def.variants()[*variant_index].name == rustc_span::sym::$variant + } => $variant_expr, + )* + $( + $pat $(if $guard)? => $expr, )* #[allow(unreachable_patterns)] _ => return Err($self.expr_error(expr_id, $expected)) @@ -172,7 +181,8 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ExprKind::Block { block } => &self.thir[*block].stmts, ); for (i, block_def) in block_defs.iter().enumerate() { - let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?; + let is_cleanup = self.body.basic_blocks_mut()[BasicBlock::from_usize(i)].is_cleanup; + let block = self.parse_block_def(self.statement_as_expr(*block_def)?, is_cleanup)?; self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block; } @@ -181,15 +191,28 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn parse_block_decls(&mut self, stmts: impl Iterator) -> PResult<()> { for stmt in stmts { - let (var, _, _) = self.parse_let_statement(stmt)?; - let data = BasicBlockData::new(None); - let block = self.body.basic_blocks_mut().push(data); - self.block_map.insert(var, block); + self.parse_basic_block_decl(stmt)?; } - Ok(()) } + fn parse_basic_block_decl(&mut self, stmt: StmtId) -> PResult<()> { + match &self.thir[stmt].kind { + StmtKind::Let { pattern, initializer: Some(initializer), .. } => { + let (var, ..) = self.parse_var(pattern)?; + let mut data = BasicBlockData::new(None); + data.is_cleanup = parse_by_kind!(self, *initializer, _, "basic block declaration", + @variant(mir_basic_block, Normal) => false, + @variant(mir_basic_block, Cleanup) => true, + ); + let block = self.body.basic_blocks_mut().push(data); + self.block_map.insert(var, block); + Ok(()) + } + _ => Err(self.stmt_error(stmt, "let statement with an initializer")), + } + } + fn parse_local_decls(&mut self, mut stmts: impl Iterator) -> PResult<()> { let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?; self.local_map.insert(ret_var, Local::from_u32(0)); @@ -219,7 +242,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { }; let span = self.thir[expr].span; let (name, operand) = parse_by_kind!(self, expr, _, "debuginfo", - @call("mir_debuginfo", args) => { + @call(mir_debuginfo, args) => { (args[0], args[1]) }, ); @@ -281,12 +304,13 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { } } - fn parse_block_def(&self, expr_id: ExprId) -> PResult> { + fn parse_block_def(&self, expr_id: ExprId, is_cleanup: bool) -> PResult> { let block = parse_by_kind!(self, expr_id, _, "basic block", ExprKind::Block { block } => &self.thir[*block], ); let mut data = BasicBlockData::new(None); + data.is_cleanup = is_cleanup; for stmt_id in &*block.stmts { let stmt = self.statement_as_expr(*stmt_id)?; let span = self.thir[stmt].span; diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index fd2c57a0a6f1..4ce7f831c871 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -13,19 +13,19 @@ use super::{parse_by_kind, PResult, ParseCtxt}; impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { pub fn parse_statement(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, _, "statement", - @call("mir_storage_live", args) => { + @call(mir_storage_live, args) => { Ok(StatementKind::StorageLive(self.parse_local(args[0])?)) }, - @call("mir_storage_dead", args) => { + @call(mir_storage_dead, args) => { Ok(StatementKind::StorageDead(self.parse_local(args[0])?)) }, - @call("mir_deinit", args) => { + @call(mir_deinit, args) => { Ok(StatementKind::Deinit(Box::new(self.parse_place(args[0])?))) }, - @call("mir_retag", args) => { + @call(mir_retag, args) => { Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?))) }, - @call("mir_set_discriminant", args) => { + @call(mir_set_discriminant, args) => { let place = self.parse_place(args[0])?; let var = self.parse_integer_literal(args[1])? as u32; Ok(StatementKind::SetDiscriminant { @@ -43,24 +43,30 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { pub fn parse_terminator(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "terminator", - @call("mir_return", _args) => { + @call(mir_return, _args) => { Ok(TerminatorKind::Return) }, - @call("mir_goto", args) => { + @call(mir_goto, args) => { Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } ) }, - @call("mir_unreachable", _args) => { + @call(mir_unreachable, _args) => { Ok(TerminatorKind::Unreachable) }, - @call("mir_drop", args) => { + @call(mir_unwind_resume, _args) => { + Ok(TerminatorKind::UnwindResume) + }, + @call(mir_unwind_terminate, args) => { + Ok(TerminatorKind::UnwindTerminate(self.parse_unwind_terminate_reason(args[0])?)) + }, + @call(mir_drop, args) => { Ok(TerminatorKind::Drop { place: self.parse_place(args[0])?, target: self.parse_block(args[1])?, - unwind: UnwindAction::Continue, + unwind: self.parse_unwind_action(args[2])?, replace: false, }) }, - @call("mir_call", args) => { + @call(mir_call, args) => { self.parse_call(args) }, ExprKind::Match { scrutinee, arms, .. } => { @@ -70,6 +76,34 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ) } + fn parse_unwind_terminate_reason(&self, expr_id: ExprId) -> PResult { + parse_by_kind!(self, expr_id, _, "unwind terminate reason", + @variant(mir_unwind_terminate_reason, Abi) => { + Ok(UnwindTerminateReason::Abi) + }, + @variant(mir_unwind_terminate_reason, InCleanup) => { + Ok(UnwindTerminateReason::InCleanup) + }, + ) + } + + fn parse_unwind_action(&self, expr_id: ExprId) -> PResult { + parse_by_kind!(self, expr_id, _, "unwind action", + @call(mir_unwind_continue, _args) => { + Ok(UnwindAction::Continue) + }, + @call(mir_unwind_unreachable, _args) => { + Ok(UnwindAction::Unreachable) + }, + @call(mir_unwind_terminate, args) => { + Ok(UnwindAction::Terminate(self.parse_unwind_terminate_reason(args[0])?)) + }, + @call(mir_unwind_cleanup, args) => { + Ok(UnwindAction::Cleanup(self.parse_block(args[0])?)) + }, + ) + } + fn parse_match(&self, arms: &[ArmId], span: Span) -> PResult { let Some((otherwise, rest)) = arms.split_last() else { return Err(ParseError { @@ -113,6 +147,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ); let destination = self.parse_place(destination)?; let target = self.parse_block(args[1])?; + let unwind = self.parse_unwind_action(args[2])?; parse_by_kind!(self, call, _, "function call", ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => { @@ -126,7 +161,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { args, destination, target: Some(target), - unwind: UnwindAction::Continue, + unwind, call_source: if *from_hir_call { CallSource::Normal } else { CallSource::OverloadedOperator }, @@ -138,25 +173,25 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn parse_rvalue(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "rvalue", - @call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant), - @call("mir_cast_transmute", args) => { + @call(mir_discriminant, args) => self.parse_place(args[0]).map(Rvalue::Discriminant), + @call(mir_cast_transmute, args) => { let source = self.parse_operand(args[0])?; Ok(Rvalue::Cast(CastKind::Transmute, source, expr.ty)) }, - @call("mir_checked", args) => { + @call(mir_checked, args) => { parse_by_kind!(self, args[0], _, "binary op", ExprKind::Binary { op, lhs, rhs } => Ok(Rvalue::CheckedBinaryOp( *op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?)) )), ) }, - @call("mir_offset", args) => { + @call(mir_offset, args) => { let ptr = self.parse_operand(args[0])?; let offset = self.parse_operand(args[1])?; Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset)))) }, - @call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)), - @call("mir_copy_for_deref", args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)), + @call(mir_len, args) => Ok(Rvalue::Len(self.parse_place(args[0])?)), + @call(mir_copy_for_deref, args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)), ExprKind::Borrow { borrow_kind, arg } => Ok( Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?) ), @@ -206,9 +241,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { pub fn parse_operand(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "operand", - @call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move), - @call("mir_static", args) => self.parse_static(args[0]), - @call("mir_static_mut", args) => self.parse_static(args[0]), + @call(mir_move, args) => self.parse_place(args[0]).map(Operand::Move), + @call(mir_static, args) => self.parse_static(args[0]), + @call(mir_static_mut, args) => self.parse_static(args[0]), ExprKind::Literal { .. } | ExprKind::NamedConst { .. } | ExprKind::NonHirLiteral { .. } @@ -229,7 +264,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn parse_place_inner(&self, expr_id: ExprId) -> PResult<(Place<'tcx>, PlaceTy<'tcx>)> { let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place", - @call("mir_field", args) => { + @call(mir_field, args) => { let (parent, ty) = self.parse_place_inner(args[0])?; let field = FieldIdx::from_u32(self.parse_integer_literal(args[1])? as u32); let field_ty = ty.field_ty(self.tcx, field); @@ -237,7 +272,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { let place = parent.project_deeper(&[proj], self.tcx); return Ok((place, PlaceTy::from_ty(field_ty))); }, - @call("mir_variant", args) => { + @call(mir_variant, args) => { (args[0], PlaceElem::Downcast( None, VariantIdx::from_u32(self.parse_integer_literal(args[1])? as u32) @@ -245,7 +280,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { }, ExprKind::Deref { arg } => { parse_by_kind!(self, *arg, _, "does not matter", - @call("mir_make_place", args) => return self.parse_place_inner(args[0]), + @call(mir_make_place, args) => return self.parse_place_inner(args[0]), _ => (*arg, PlaceElem::Deref), ) }, diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index c6a09f6568a5..7e9191a37d32 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 a43aae6f4494..304870274ac6 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 58d6be50b905..886d805454db 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); +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 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:?}"), - } + 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 45be50153713..fcb563607828 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, + + /// 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 5bfce3ab5100..418f9bb9de94 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, } #[derive(LintDiagnostic)] @@ -37,6 +39,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -45,6 +49,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -53,6 +59,8 @@ pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -61,6 +69,8 @@ pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -69,6 +79,8 @@ pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -77,6 +89,8 @@ pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -85,6 +99,8 @@ pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -93,6 +109,8 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -100,6 +118,8 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[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, } #[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(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, + 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 b6adb383fa6b..bcd9140f0e18 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 933653e708e9..8c3d09c19a15 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>, + /// 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( + &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>, + ) -> 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, 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, + ) -> 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; + fn check_let(&mut self, pat: &Pat<'tcx>, scrutinee: Option, 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, + ); + } } - if let Err(err) = pat.pat_error_reported() { - self.error = Err(err); - return; - } - 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>, + whole_chain_span: Span, ) { - if let LetSource::None = let_source { - return; - } + assert!(self.let_source != LetSource::None); - // 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)); - - 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> { } } + 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)) + } + + fn is_let_irrefutable(&mut self, pat: &Pat<'tcx>) -> Result { + 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 }) + } + #[instrument(level = "trace", skip(self))] - fn check_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option) { - // 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 check_binding_is_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option) { + let pattern_ty = pat.ty; - let mut cx = self.new_cx(self.lint_level, false); - - 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()); - - // 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> { } } +/// 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 }); + } +} + 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, - name, + 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 }, - ) - } - }); -} - -/// 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, + ty_path, + name, + }, + ) } } -fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option) { - tcx.emit_spanned_lint( - UNREACHABLE_PATTERNS, - id, - span, - UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall }, - ); -} - -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| { + 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>, -) { - if matches!(pat.ctor(), Constructor::NonExhaustive) { - 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, } - 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)) } /// 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>, +) { + 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> { 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() }; + 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? + }; - 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 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>, ) -> Vec { @@ -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 fc03f7891a86..48a590f5d37f 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 1eb1dd72a61d..da7b6587a722 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>, + /// The span of the whole match, if applicable. + pub(crate) match_span: Option, /// 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 1e8e09ac333b..01acc380fa39 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 c1152e88cd0f..bdfb6a6ff6b1 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 28765af20ad3..42b2f18869c2 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; + } + + // 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, }; - 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); + 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 d435d3ee69b7..5b4bc4fa1342 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 53c0d0dea292..0adbb078105a 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 be4af3b76f1e..f5db7ce97eba 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 fc30a718cbb5..dfafd8598306 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>>, } +/// 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 704eea413e11..b318134ae672 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 4d0e261ed1fd..261d9dd448d4 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 5aa3c3cfe4dd..9f59f9d12452 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 427cc1e19241..7de4ca667949 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 8dc7b60c4e53..3a6e1ef34883 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -40,7 +40,8 @@ impl SsaLocals { let dominators = body.basic_blocks.dominators(); let direct_uses = IndexVec::from_elem(0, &body.local_decls); - let mut visitor = SsaVisitor { assignments, assignment_order, dominators, direct_uses }; + let mut visitor = + SsaVisitor { body, assignments, assignment_order, dominators, direct_uses }; for local in body.args_iter() { visitor.assignments[local] = Set1::One(DefLocation::Argument); @@ -110,7 +111,7 @@ impl SsaLocals { body: &'a Body<'tcx>, ) -> impl Iterator, Location)> + 'a { self.assignment_order.iter().filter_map(|&local| { - if let Set1::One(DefLocation::Body(loc)) = self.assignments[local] { + if let Set1::One(DefLocation::Assignment(loc)) = self.assignments[local] { let stmt = body.stmt_at(loc).left()?; // `loc` must point to a direct assignment to `local`. let Some((target, rvalue)) = stmt.kind.as_assign() else { bug!() }; @@ -134,21 +135,21 @@ impl SsaLocals { AssignedValue::Arg, Location { block: START_BLOCK, statement_index: 0 }, ), - Set1::One(DefLocation::Body(loc)) => { + Set1::One(DefLocation::Assignment(loc)) => { let bb = &mut basic_blocks[loc.block]; - let value = if loc.statement_index < bb.statements.len() { - // `loc` must point to a direct assignment to `local`. - let stmt = &mut bb.statements[loc.statement_index]; - let StatementKind::Assign(box (target, ref mut rvalue)) = stmt.kind else { - bug!() - }; - assert_eq!(target.as_local(), Some(local)); - AssignedValue::Rvalue(rvalue) - } else { - let term = bb.terminator_mut(); - AssignedValue::Terminator(&mut term.kind) + // `loc` must point to a direct assignment to `local`. + let stmt = &mut bb.statements[loc.statement_index]; + let StatementKind::Assign(box (target, ref mut rvalue)) = stmt.kind else { + bug!() }; - f(local, value, loc) + assert_eq!(target.as_local(), Some(local)); + f(local, AssignedValue::Rvalue(rvalue), loc) + } + Set1::One(DefLocation::CallReturn { call, .. }) => { + let bb = &mut basic_blocks[call]; + let loc = Location { block: call, statement_index: bb.statements.len() }; + let term = bb.terminator_mut(); + f(local, AssignedValue::Terminator(&mut term.kind), loc) } _ => {} } @@ -201,14 +202,15 @@ impl SsaLocals { } } -struct SsaVisitor<'a> { +struct SsaVisitor<'tcx, 'a> { + body: &'a Body<'tcx>, dominators: &'a Dominators, assignments: IndexVec>, assignment_order: Vec, direct_uses: IndexVec, } -impl SsaVisitor<'_> { +impl SsaVisitor<'_, '_> { fn check_dominates(&mut self, local: Local, loc: Location) { let set = &mut self.assignments[local]; let assign_dominates = match *set { @@ -224,7 +226,7 @@ impl SsaVisitor<'_> { } } -impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { +impl<'tcx> Visitor<'tcx> for SsaVisitor<'tcx, '_> { fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) { match ctxt { PlaceContext::MutatingUse(MutatingUseContext::Projection) @@ -234,7 +236,7 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { // so we have to remove them too. PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::ShallowBorrow + | NonMutatingUseContext::FakeBorrow | NonMutatingUseContext::AddressOf, ) | PlaceContext::MutatingUse(_) => { @@ -250,9 +252,18 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> { fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, loc: Location) { let location = match ctxt { - PlaceContext::MutatingUse( - MutatingUseContext::Store | MutatingUseContext::Call | MutatingUseContext::Yield, - ) => Some(DefLocation::Body(loc)), + PlaceContext::MutatingUse(MutatingUseContext::Store) => { + Some(DefLocation::Assignment(loc)) + } + PlaceContext::MutatingUse(MutatingUseContext::Call) => { + let call = loc.block; + let TerminatorKind::Call { target, .. } = + self.body.basic_blocks[call].terminator().kind + else { + bug!() + }; + Some(DefLocation::CallReturn { call, target }) + } _ => None, }; if let Some(location) = location @@ -359,7 +370,7 @@ impl StorageLiveLocals { for (statement_index, statement) in bbdata.statements.iter().enumerate() { if let StatementKind::StorageLive(local) = statement.kind { storage_live[local] - .insert(DefLocation::Body(Location { block, statement_index })); + .insert(DefLocation::Assignment(Location { block, statement_index })); } } } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index e51b672205c2..266190da035e 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 20b4292701e3..8ab1ec298a1c 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(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 31d91fe80bd6..db795ce9f723 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>) -> Vec> { + // If there are unclosed delims, see if there are diff markers and if so, point them + // out instead of complaining about the unclosed delims. + let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None); + let mut diff_errs = vec![]; + // Suggest removing a `{` we think appears in an `if`/`while` condition + // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, but + // we have no way of tracking this in the lexer itself, so we piggyback on the parser + let mut in_cond = false; + while parser.token != token::Eof { + if let Err(diff_err) = parser.err_diff_marker() { + diff_errs.push(diff_err); + } else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) { + in_cond = true; + } else if matches!( + parser.token.kind, + token::CloseDelim(Delimiter::Brace) | token::FatArrow + ) { + // end of the `if`/`while` body, or the end of a `match` guard + in_cond = false; + } else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) { + // Store the `&&` and `let` to use their spans later when creating the diagnostic + let maybe_andand = parser.look_ahead(1, |t| t.clone()); + let maybe_let = parser.look_ahead(2, |t| t.clone()); + if maybe_andand == token::OpenDelim(Delimiter::Brace) { + // This might be the beginning of the `if`/`while` body (i.e., the end of the condition) + in_cond = false; + } else if maybe_andand == token::AndAnd && maybe_let.is_keyword(kw::Let) { + let mut err = parser.struct_span_err( + parser.token.span, + "found a `{` in the middle of a let-chain", + ); + err.span_suggestion( + parser.token.span, + "consider removing this brace to parse the `let` as part of the same chain", + "", + Applicability::MachineApplicable, + ); + err.span_label( + maybe_andand.span.to(maybe_let.span), + "you might have meant to continue the let-chain here", + ); + errs.push(err); + } + } + parser.bump(); + } + if !diff_errs.is_empty() { + errs.iter_mut().for_each(|err| { + err.delay_as_bug(); + }); + return diff_errs; + } + return errs; + } + fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> { // An unexpected closing delimiter (i.e., there is no // matching opening delimiter). diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 36125e138b2d..235b28b6e26e 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 253dd2a3b340..801860c21236 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() 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 1a7ae4069114..76f3f21a5164 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 be2cbaf3020e..dc0f13965230 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> { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 2e8c58b0241f..6b2b842543a8 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 4bb7e65747f7..4b3b82c59cfb 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::( diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index edcc22d56c68..93db6cfc4635 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 f792b8f2cdd5..e1eb58fecc7d 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::>(); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c94e0d0ed394..add40b83d21d 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 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 7510a41485af..077126364454 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 = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), - cross_crate_inline_threshold: Option = (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 = (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 = (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 80a549b30f79..e9655a5587db 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, } -pub struct PerfStats { - /// The accumulated time spent on computing symbol hashes. - pub symbol_hash_time: Lock, - /// 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 1ad8620bfba5..c0c088bcef7d 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 78144524ac50..7cfdbbbf7037 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 4d2a518226d8..f0b368bec39c 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 25bd82bf1ef5..170f53a7a698 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 8b4f77a05661..26c5711099c6 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 36731d0fe747..988ff57254c5 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 fc13bdff36f5..489c8d189265 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 ff470ce1fa07..302be85a429f 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 53925eeaaa0d..0178ff53b24a 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); + // 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); + // 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); - } + // 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 5ce188488ce5..80dec80bf03a 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[][]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 ad3d291dfa08..01cbee3a7159 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 ddecbb1a8c4a..000000000000 --- 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 similarity index 100% rename from compiler/rustc_target/src/spec/abi.rs rename to 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 6c16b03cc283..000000000000 --- 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 similarity index 100% rename from compiler/rustc_target/src/spec/aix_base.rs rename to 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 similarity index 85% rename from compiler/rustc_target/src/spec/android_base.rs rename to compiler/rustc_target/src/spec/base/android.rs index 9c1df1a06778..af15c16a5a9a 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 similarity index 98% rename from compiler/rustc_target/src/spec/apple_base.rs rename to compiler/rustc_target/src/spec/base/apple/mod.rs index 7a666eea437d..99e64503e257 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 similarity index 97% rename from compiler/rustc_target/src/spec/apple/tests.rs rename to compiler/rustc_target/src/spec/base/apple/tests.rs index 3b23ddadcc47..f13058ebc82a 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 similarity index 100% rename from compiler/rustc_target/src/spec/avr_gnu_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/bpf_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/dragonfly_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/freebsd_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/fuchsia_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/haiku_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/hermit_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/hurd_base.rs rename to 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 000000000000..3501dbdea1b5 --- /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 similarity index 100% rename from compiler/rustc_target/src/spec/illumos_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/l4re_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/linux_base.rs rename to 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 000000000000..3491277c4407 --- /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 similarity index 80% rename from compiler/rustc_target/src/spec/linux_musl_base.rs rename to compiler/rustc_target/src/spec/base/linux_musl.rs index b698bcbcef69..5117cadbee0e 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 similarity index 69% rename from compiler/rustc_target/src/spec/linux_ohos_base.rs rename to compiler/rustc_target/src/spec/base/linux_ohos.rs index 4ad4c837336f..273e6a98dd4d 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 000000000000..540344e9e94d --- /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 000000000000..d137aaa53585 --- /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 similarity index 100% rename from compiler/rustc_target/src/spec/msvc_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/netbsd_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/nto_qnx_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/openbsd_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/redox_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/solaris_base.rs rename to 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 similarity index 83% rename from compiler/rustc_target/src/spec/solid_base.rs rename to compiler/rustc_target/src/spec/base/solid.rs index eaf72b7616c7..ce4a8869001b 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 similarity index 84% rename from compiler/rustc_target/src/spec/teeos_base.rs rename to compiler/rustc_target/src/spec/base/teeos.rs index 1bc71bab0160..38d0a6d73140 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 similarity index 100% rename from compiler/rustc_target/src/spec/thumb_base.rs rename to 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 similarity index 95% rename from compiler/rustc_target/src/spec/uefi_msvc_base.rs rename to compiler/rustc_target/src/spec/base/uefi_msvc.rs index a50a55ad7e02..e8acd6078e2a 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 similarity index 100% rename from compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/vxworks_base.rs rename to 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 similarity index 96% rename from compiler/rustc_target/src/spec/wasm_base.rs rename to compiler/rustc_target/src/spec/base/wasm.rs index 82a3afeae31e..87ade9e58cf4 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 similarity index 95% rename from compiler/rustc_target/src/spec/windows_gnu_base.rs rename to compiler/rustc_target/src/spec/base/windows_gnu.rs index b84e0fc07830..25f02dc14519 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 similarity index 100% rename from compiler/rustc_target/src/spec/windows_gnullvm_base.rs rename to 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 similarity index 93% rename from compiler/rustc_target/src/spec/windows_msvc_base.rs rename to compiler/rustc_target/src/spec/base/windows_msvc.rs index 21062c337d82..e3cf9757219e 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 similarity index 80% rename from compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs rename to compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs index f30c33d997e3..17256e18e24e 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 similarity index 65% rename from compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs rename to compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs index 8c942c59dd03..59a761671254 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 b9cf26d9380b..000000000000 --- 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 8d6b3f185122..000000000000 --- 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 4ba480ffecff..000000000000 --- 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 48ca5fcf3ad0..d8dd4ae2286d 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 { 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 similarity index 93% rename from compiler/rustc_target/src/spec/aarch64_apple_darwin.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs index 9ac732351411..8e6c00b1255d 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 similarity index 95% rename from compiler/rustc_target/src/spec/aarch64_apple_ios.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs index e9edfd2877b8..9fc5b5de466b 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 similarity index 96% rename from compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs index b29ab14e7f28..0172a3a9c2e8 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 similarity index 95% rename from compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs index 6e2d62b6e085..602a687779e4 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 similarity index 90% rename from compiler/rustc_target/src/spec/aarch64_apple_tvos.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs index f7cdfa71c4b6..a1a31935509c 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 similarity index 94% rename from compiler/rustc_target/src/spec/aarch64_apple_tvos_sim.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs index 909a52a5097e..7b0bbb28e476 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 similarity index 94% rename from compiler/rustc_target/src/spec/aarch64_apple_watchos_sim.rs rename to compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs index e4af4127c222..014560d2278b 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 similarity index 85% rename from compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs index b84783c0a407..bbaa870ec2e8 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 similarity index 85% rename from compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs rename to compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs index a24e0119f25e..7536e507b3d7 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 similarity index 83% rename from compiler/rustc_target/src/spec/aarch64_be_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs index 98ae05974aa8..21de8a71a0df 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 000000000000..3668db912bb8 --- /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 similarity index 84% rename from compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs rename to compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs index 437fd6015803..e5e22fd1ee28 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 similarity index 90% rename from compiler/rustc_target/src/spec/aarch64_linux_android.rs rename to compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs index 071b727b35c5..7c6fed7ab995 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 similarity index 91% rename from compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs rename to compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs index e271bdc8a015..02fcc2bb43e9 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 similarity index 100% rename from compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding_linker_script.ld rename to 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 similarity index 83% rename from compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs rename to compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs index cf1d7ca1158d..1ea738142825 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 similarity index 81% rename from compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index 56b76bc7ada9..cbd1329726a2 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 similarity index 84% rename from compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs index 84fa9814bbea..0f95984a31f5 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 similarity index 83% rename from compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs index a5683fa7348a..cacc6ea235a3 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 similarity index 82% rename from compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs index 2414867be552..3839e0b9c465 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 similarity index 88% rename from compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs index da246089440f..c0b07db38180 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 similarity index 84% rename from compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs index ad9df53c2b7f..d4c6271b241f 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 similarity index 84% rename from compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs index 523eb6bd2fe2..364df677e44a 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 similarity index 86% rename from compiler/rustc_target/src/spec/aarch64_unknown_linux_ohos.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs index c8f3db00e01b..5f3bef63aa65 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 similarity index 83% rename from compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs index a58b64d3d03a..3194d16ff473 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 similarity index 98% rename from compiler/rustc_target/src/spec/aarch64_unknown_none.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs index be27302f7f52..88fa6d5a762f 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 similarity index 91% rename from compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs index 9dfa1f268ac5..48b79b0b9bac 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 similarity index 91% rename from compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx_710.rs index 630642dcd33a..aeeaab3af323 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 similarity index 81% rename from compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs index 224e31af24f7..e3f5aafc7d44 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 similarity index 82% rename from compiler/rustc_target/src/spec/aarch64_unknown_redox.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs index 5650162cdbc9..de875e29ffdc 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 similarity index 85% rename from compiler/rustc_target/src/spec/aarch64_unknown_teeos.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs index 64a7dc681c89..eec2668d4878 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 similarity index 83% rename from compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs rename to compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs index 82fb015569d6..9ed6ed2651f3 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 similarity index 80% rename from compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs index d39442d91776..c64b2c7d113f 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 similarity index 81% rename from compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs rename to compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs index 7e2af4c7a6a4..29f61d857788 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 similarity index 95% rename from compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs rename to compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs index c757ed45e472..9931b7b866cb 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 similarity index 84% rename from compiler/rustc_target/src/spec/arm_linux_androideabi.rs rename to compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs index bbf1fa315ab4..43b27b414d88 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 similarity index 86% rename from compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs rename to compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs index 400030ca0c60..e4fa54c4b754 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 similarity index 86% rename from compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs rename to compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs index 6228fb15a83f..f379ea35ecb6 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 similarity index 89% rename from compiler/rustc_target/src/spec/arm_unknown_linux_musleabi.rs rename to compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs index 3ef441d6a607..f3d5ff892442 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 similarity index 89% rename from compiler/rustc_target/src/spec/arm_unknown_linux_musleabihf.rs rename to compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs index eb6660d4c289..f3e366d59937 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 similarity index 87% rename from compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs rename to compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs index 1d66515a72e0..07c7e1c58456 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 similarity index 100% rename from compiler/rustc_target/src/spec/armebv7r_none_eabi.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/armv4t_none_eabi.rs rename to 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 similarity index 88% rename from compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs rename to compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs index cffebcc9581c..5ab753c3d61b 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 similarity index 93% rename from compiler/rustc_target/src/spec/armv5te_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs index dfd27b654746..5e23efecdbe1 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 similarity index 87% rename from compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs rename to compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs index b940563102b0..7155ab289c0a 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 similarity index 90% rename from compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs rename to compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs index 2530971b5021..3f25ab2bcc19 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 similarity index 86% rename from compiler/rustc_target/src/spec/armv5te_unknown_linux_uclibceabi.rs rename to compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs index a51be10a3d82..af6e3baa27ae 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 similarity index 88% rename from compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs index 4a8aa31576fa..22f6ee810557 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 similarity index 87% rename from compiler/rustc_target/src/spec/armv6_unknown_netbsd_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs index 6e26f686fcb5..84d9ceac04d4 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 similarity index 100% rename from compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs rename to 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 similarity index 87% rename from compiler/rustc_target/src/spec/armv7_linux_androideabi.rs rename to compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs index 402e0fd92363..bb3e574e32fe 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 similarity index 100% rename from compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs rename to 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 similarity index 87% rename from compiler/rustc_target/src/spec/armv7_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs index bc37b62de8e2..9f4a432c6fa5 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 similarity index 88% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs index 73ae212a7a6e..ad9fd773b8b8 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 similarity index 88% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs index e39ea49a0032..aad7977d504a 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 similarity index 90% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_musleabi.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs index 7dae8577396e..7f30a5ad7d7d 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 similarity index 90% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_musleabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs index ba83964bf585..ec5c6419f639 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 similarity index 89% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_ohos.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs index e9b0bda68ef1..9f2ac541ddc9 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 similarity index 86% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs index 171f67070d54..212c80718f03 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 similarity index 88% rename from compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs index d3e95a6573d8..f760ad9e79c2 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 similarity index 87% rename from compiler/rustc_target/src/spec/armv7_unknown_netbsd_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs index c89ae2483988..e5518c6daecf 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 similarity index 85% rename from compiler/rustc_target/src/spec/armv7_wrs_vxworks_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs index c1ab90172e27..0b4e64307d28 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 similarity index 84% rename from compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabi.rs rename to compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs index b49dc650bd00..57d40d54c449 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 similarity index 84% rename from compiler/rustc_target/src/spec/armv7a_kmc_solid_asp3_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs index 7d30238e8ab2..3d21213c5ff8 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 similarity index 94% rename from compiler/rustc_target/src/spec/armv7a_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs index d59de86a2301..c5b61427e698 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 similarity index 92% rename from compiler/rustc_target/src/spec/armv7a_none_eabihf.rs rename to compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs index c134f3e09078..ba3caad6a972 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 similarity index 95% rename from compiler/rustc_target/src/spec/armv7k_apple_watchos.rs rename to compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs index 6e1d00d1f6ca..751fdcb20f19 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 similarity index 100% rename from compiler/rustc_target/src/spec/armv7r_none_eabi.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/armv7r_none_eabihf.rs rename to 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 similarity index 88% rename from compiler/rustc_target/src/spec/armv7s_apple_ios.rs rename to compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs index be7f8542c9e5..44c624c4ebde 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 similarity index 71% rename from compiler/rustc_target/src/spec/asmjs_unknown_emscripten.rs rename to compiler/rustc_target/src/spec/targets/asmjs_unknown_emscripten.rs index f492c3451a41..e4768c67af55 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 000000000000..bf01413a80ad --- /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 similarity index 73% rename from compiler/rustc_target/src/spec/bpfeb_unknown_none.rs rename to compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs index 174ddfa50bfc..91e091e237af 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 similarity index 72% rename from compiler/rustc_target/src/spec/bpfel_unknown_none.rs rename to compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs index 7625e7b0e48e..45ab750ead6f 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 similarity index 88% rename from compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs rename to compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs index 93becd708693..14cd33a260a7 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 similarity index 89% rename from compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2hf.rs rename to compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs index 745188341603..0ce271c601ce 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 similarity index 89% rename from compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs index 4c6ab5f5ae45..98a5e7abd09d 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 similarity index 92% rename from compiler/rustc_target/src/spec/i386_apple_ios.rs rename to compiler/rustc_target/src/spec/targets/i386_apple_ios.rs index 5819981612e8..ed2c990ffa64 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 similarity index 100% rename from compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs rename to 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 similarity index 82% rename from compiler/rustc_target/src/spec/i586_pc_nto_qnx700.rs rename to compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs index 68afa7fe4012..06089391623b 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 similarity index 100% rename from compiler/rustc_target/src/spec/i586_pc_windows_msvc.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/i586_unknown_linux_gnu.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/i586_unknown_linux_musl.rs rename to 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 similarity index 82% rename from compiler/rustc_target/src/spec/i586_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs index 0d8bdc3f89f7..8375fa4c0c0f 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 similarity index 94% rename from compiler/rustc_target/src/spec/i686_apple_darwin.rs rename to compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index b5103d15db69..242fe5ed98a9 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 similarity index 85% rename from compiler/rustc_target/src/spec/i686_linux_android.rs rename to compiler/rustc_target/src/spec/targets/i686_linux_android.rs index c7c30c23901d..987265598ebc 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 similarity index 88% rename from compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs rename to compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs index 7a11138754fa..8d4a39b58114 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 similarity index 87% rename from compiler/rustc_target/src/spec/i686_pc_windows_gnullvm.rs rename to compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs index 3154b512a520..bb410cd8caf2 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 similarity index 91% rename from compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs index db4c00dc697d..ba80c23196e1 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 similarity index 82% rename from compiler/rustc_target/src/spec/i686_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs index 35ca78034f17..70aa0b47962e 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 similarity index 81% rename from compiler/rustc_target/src/spec/i686_unknown_haiku.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs index e6b72336c5cf..9715f6c21d90 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 similarity index 83% rename from compiler/rustc_target/src/spec/i686_unknown_hurd_gnu.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs index 29f803601381..9102673ef779 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 similarity index 81% rename from compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs index 73e536a7e4d9..0ca058b2fd2a 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 similarity index 90% rename from compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs index 3825082ba25e..ce0df3a72344 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 similarity index 81% rename from compiler/rustc_target/src/spec/i686_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs index b191996c7de0..2a3ac5932d35 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 similarity index 82% rename from compiler/rustc_target/src/spec/i686_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs index 8babe5597128..45883542bead 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 similarity index 98% rename from compiler/rustc_target/src/spec/i686_unknown_uefi.rs rename to compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs index a2e42c5e61d5..25315e19cddb 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 similarity index 87% rename from compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs rename to compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs index a3e32569827f..ec211a710eb0 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 similarity index 82% rename from compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs index 4c657fe908ac..7cca2fc6b9f7 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 similarity index 81% rename from compiler/rustc_target/src/spec/i686_wrs_vxworks.rs rename to compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs index b5cfdfcebea9..965a895972c6 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 similarity index 83% rename from compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs index db8b9c70e670..0f05e7c475a8 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 similarity index 85% rename from compiler/rustc_target/src/spec/loongarch64_unknown_none.rs rename to compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs index dbc96d68eae1..3b1ea8e206f1 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 similarity index 86% rename from compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs rename to compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs index c4d5c7bc44cc..ab9300ef9c72 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 similarity index 82% rename from compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs index 9bcd56bed002..b54f5d753cc3 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 similarity index 88% rename from compiler/rustc_target/src/spec/mips64_openwrt_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs index 3c6ef52c6cd7..6191a6dfd415 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 similarity index 87% rename from compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs rename to compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs index b9df0046b12b..e1131f07f264 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 similarity index 86% rename from compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs rename to compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs index 465e97a026c5..147c1c224761 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 similarity index 86% rename from compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs rename to compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs index 57ad8c47399b..4c612554d204 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 similarity index 84% rename from compiler/rustc_target/src/spec/mips64el_unknown_linux_muslabi64.rs rename to compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs index 75575eb7eebd..d60404f0ce53 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 similarity index 85% rename from compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs index 8df8b0b4c2c7..c49b89bbd465 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 similarity index 84% rename from compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs index c2846313a9eb..92d2d9d84c1d 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 similarity index 85% rename from compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs rename to compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs index c59bb5fdd223..51df0a974cb1 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 similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_sony_psp.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_sony_psp_linker_script.ld rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_sony_psx.rs rename to 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 similarity index 84% rename from compiler/rustc_target/src/spec/mipsel_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs index 01346e71a92f..c2e482148cd7 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 similarity index 83% rename from compiler/rustc_target/src/spec/mipsel_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs index 0e8f1a2c8e0e..5eed050453d1 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 similarity index 83% rename from compiler/rustc_target/src/spec/mipsel_unknown_linux_uclibc.rs rename to compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs index 8342074586bc..77e69119d167 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 similarity index 85% rename from compiler/rustc_target/src/spec/mipsel_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs index 651358d6422c..706a1af3e154 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 similarity index 100% rename from compiler/rustc_target/src/spec/mipsel_unknown_none.rs rename to 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 similarity index 85% rename from compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs index 983a449b006a..59783882e186 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 similarity index 84% rename from compiler/rustc_target/src/spec/mipsisa32r6el_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs index ec0facdfb7bf..c3d79412e1c8 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 similarity index 87% rename from compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs rename to compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs index 16dd1c416f4f..2ae6e7521f94 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 similarity index 86% rename from compiler/rustc_target/src/spec/mipsisa64r6el_unknown_linux_gnuabi64.rs rename to compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs index 8d0a6aa8f514..31637e9f6d02 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 similarity index 100% rename from compiler/rustc_target/src/spec/msp430_none_elf.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs rename to 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 similarity index 83% rename from compiler/rustc_target/src/spec/powerpc64_ibm_aix.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs index 4e105a03e287..c512e4c7c489 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 similarity index 80% rename from compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs index e8fe55a00db0..e470ec05eff5 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 similarity index 81% rename from compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs index 7a0cc539f1a8..34e3184d348e 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 similarity index 81% rename from compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs index f80b22828c1d..e2e707f4a1ac 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 similarity index 80% rename from compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs index 3643f7b0c374..ebaeb04be315 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 similarity index 80% rename from compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs rename to compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs index b0472e64e134..e2085ba7ce3e 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 similarity index 79% rename from compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs index 342b1cf4f4ca..b399d36d8b24 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 similarity index 80% rename from compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs index 815e3d2781ca..194c3170e683 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 similarity index 79% rename from compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs index 0b9b78bcec89..1f53e6895983 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 similarity index 84% rename from compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs index e036f5bdbada..6d094f9a3676 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 similarity index 79% rename from compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs index c8d6f8b9c676..1600698da44a 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 similarity index 81% rename from compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs index fdaa9d366d92..af0fbfebef22 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 similarity index 79% rename from compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs index 7fe708cf5304..9b0ac4a0fc9b 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 similarity index 79% rename from compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs index 6f8875ba7b40..bc2e239d9a52 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 similarity index 81% rename from compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs index 280d36698b48..081aaaea2499 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 similarity index 80% rename from compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs rename to compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs index 6f245e6ab62a..e8bccc153850 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 similarity index 84% rename from compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs rename to compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs index 1d5a5e5c6ac6..fa4ef098e038 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 similarity index 83% rename from compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs index bffd377bc4a1..06e8f1837637 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 similarity index 83% rename from compiler/rustc_target/src/spec/riscv32gc_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs index c9f3acffb77b..722703d2384f 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 similarity index 100% rename from compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/riscv32imac_esp_espidf.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs rename to 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 similarity index 100% rename from compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs rename to 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 similarity index 83% rename from compiler/rustc_target/src/spec/riscv64_linux_android.rs rename to compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs index 121237f6ba43..40e447dbb836 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 similarity index 84% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs index 8281bac10f88..2c7878de8120 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 similarity index 83% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_fuchsia.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs index 0585ed76fe81..a29470c24fbd 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 similarity index 83% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs index 1f6a34c0cacc..b7e29d2da3dc 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 similarity index 83% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs index 90dccb28063d..c0969d4e11eb 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 similarity index 83% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs index 1a56c78e6852..656e260d094d 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 similarity index 85% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs index a89bd363a47e..43a313a94080 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 similarity index 96% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs index ab3c14e3fe73..f29e224244ef 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 similarity index 84% rename from compiler/rustc_target/src/spec/riscv64gc_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs index ade9d77624bd..1f1da7d5a29e 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 similarity index 100% rename from compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs rename to 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 similarity index 90% rename from compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs index f2c722b9a89d..6fc410eb2235 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 similarity index 90% rename from compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs index 8fe9d023c527..03772aab372a 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 similarity index 82% rename from compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs index 39efd8f305cd..20ec9a84e8b8 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 similarity index 80% rename from compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs index 38ab066b0879..c8c0fd2e134c 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 similarity index 81% rename from compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs index 06a5f782a6df..82ce610066a2 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 similarity index 81% rename from compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs index b10e6264b73c..548fbb9ed52d 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 similarity index 100% rename from compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs rename to 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 similarity index 88% rename from compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs rename to compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs index 4d2bc98ab783..16cd991dd286 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 similarity index 95% rename from compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs index 88a76f49acd6..7b5c019b1bb5 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 similarity index 93% rename from compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs index 021b0e0eb622..d9212afb084c 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 similarity index 91% rename from compiler/rustc_target/src/spec/thumbv6m_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs index c9bb0112f0e3..ac076fb8864e 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 similarity index 89% rename from compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs index f1be274f067c..128ac1dd1792 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 similarity index 83% rename from compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs index 65c2f5a704b7..810ed6a24044 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 similarity index 91% rename from compiler/rustc_target/src/spec/thumbv7em_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs index 000e5f2d3c6b..1752f1d9aacf 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 similarity index 94% rename from compiler/rustc_target/src/spec/thumbv7em_none_eabihf.rs rename to compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs index 39a72564e49a..c113c62fc1d8 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 similarity index 83% rename from compiler/rustc_target/src/spec/thumbv7m_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs index ab25cde66c7c..f9ab3ce1ad08 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 similarity index 89% rename from compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs index 624837a22d60..c07aa944d7e3 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 similarity index 91% rename from compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_gnueabihf.rs rename to compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs index b500c50de985..b4045037c6ab 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 similarity index 93% rename from compiler/rustc_target/src/spec/thumbv7neon_unknown_linux_musleabihf.rs rename to compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs index dce0cbcef026..6ef30f10fe44 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 similarity index 87% rename from compiler/rustc_target/src/spec/thumbv8m_base_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs index 756b1834c827..bf62574867a6 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 similarity index 85% rename from compiler/rustc_target/src/spec/thumbv8m_main_none_eabi.rs rename to compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs index 4b6268546549..07fc7feade59 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 similarity index 91% rename from compiler/rustc_target/src/spec/thumbv8m_main_none_eabihf.rs rename to compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs index 86c25f9e4b99..61d4e8fc802e 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 similarity index 87% rename from compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs rename to compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs index 6f77ef98c015..394f02ecac49 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 similarity index 95% rename from compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs rename to compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs index 06529c2e4039..2a40d9c66370 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 . -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 similarity index 96% rename from compiler/rustc_target/src/spec/wasm32_wasi.rs rename to compiler/rustc_target/src/spec/targets/wasm32_wasi.rs index 23fabcdc90de..6dbcb01ea436 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 similarity index 97% rename from compiler/rustc_target/src/spec/wasm32_wasi_preview1_threads.rs rename to compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs index ba9a99ae380e..28ea4cc9ece3 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 similarity index 94% rename from compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs rename to compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs index 3fda398d24c8..54c5ae8e2030 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 similarity index 94% rename from compiler/rustc_target/src/spec/x86_64_apple_darwin.rs rename to compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index e3f5d7321d13..9170a10d254b 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 similarity index 90% rename from compiler/rustc_target/src/spec/x86_64_apple_ios.rs rename to compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs index 061b6a96fc88..d9f3f7de655c 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 similarity index 95% rename from compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs rename to compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs index fd1926f29456..5e6fbac34d71 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 similarity index 89% rename from compiler/rustc_target/src/spec/x86_64_apple_tvos.rs rename to compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs index 2ec4d9569e3e..1c4d9196c185 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 similarity index 93% rename from compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs rename to compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs index 5fcc00a86ff9..258148677fb8 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 similarity index 97% rename from compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs rename to compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs index a7ed74f47212..f4117edc3ff5 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 000000000000..46df00e9c02b --- /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 similarity index 83% rename from compiler/rustc_target/src/spec/x86_64_linux_android.rs rename to compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs index c110674fd870..6cffda44fa9e 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 similarity index 83% rename from compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs rename to compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs index 8424757df076..93aec4c425a2 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 similarity index 83% rename from compiler/rustc_target/src/spec/x86_64_pc_solaris.rs rename to compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs index e2c59d2938e6..ca6a6dc500b8 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 similarity index 87% rename from compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs rename to compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs index 1b8885c34da7..6d3e07270517 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 similarity index 83% rename from compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs rename to compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs index 8f5e398a0be9..a56ebfa585e2 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 similarity index 83% rename from compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs index 6b897ca7070e..7d6276a0c2d5 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 similarity index 83% rename from compiler/rustc_target/src/spec/x86_64_sun_solaris.rs rename to compiler/rustc_target/src/spec/targets/x86_64_sun_solaris.rs index 650065f6330a..cca099d3bbf6 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 similarity index 81% rename from compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs index 2aa093b131f5..c12cb1ab00e0 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 similarity index 81% rename from compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs index 3b8e75977b5a..68d1a755b792 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 similarity index 84% rename from compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs index b2d91d09996f..e3f29fa5afaf 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 similarity index 83% rename from compiler/rustc_target/src/spec/x86_64_unknown_fuchsia.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs index bee935419602..c8850d703e35 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 similarity index 85% rename from compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs index 16ed3150e6e2..ca55e6514ddd 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 similarity index 84% rename from compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs index 1eb069301117..3cc50d40dda6 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 similarity index 86% rename from compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs index 9259cfe5f0ed..eb2b13cb5c26 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 similarity index 83% rename from compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs index 912d289c47f9..7b86fe738b1e 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 similarity index 86% rename from compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs index 2f970f87cc64..80e267c163fa 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 similarity index 86% rename from compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs index 5469d02c5923..622bfe8bbe8e 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 similarity index 85% rename from compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs index 7154f5fa3068..d74ff466a015 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 similarity index 86% rename from compiler/rustc_target/src/spec/x86_64_unknown_linux_ohos.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs index a96be8cd5546..87b004df0018 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 similarity index 83% rename from compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs index 2e7bf34f7d2f..04060513abc8 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 similarity index 89% rename from compiler/rustc_target/src/spec/x86_64_unknown_none.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs index fe3b24f2d4af..9aa95a35f8e5 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 similarity index 82% rename from compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs index 86fa9bf7ed2a..5e6e7efb2de8 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 similarity index 82% rename from compiler/rustc_target/src/spec/x86_64_unknown_redox.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs index decc97367822..382ff71f019c 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 similarity index 94% rename from compiler/rustc_target/src/spec/x86_64_unknown_uefi.rs rename to compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs index 41ba768068a3..5abfb8162f70 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 similarity index 86% rename from compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs rename to compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs index 1a9d2a57182d..a46d3a0e27bc 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 similarity index 82% rename from compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs rename to compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs index 1ae403fa83f3..a3bc27aa0650 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 similarity index 83% rename from compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs rename to compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs index a7c4aaecf910..4b221fe6959f 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 similarity index 97% rename from compiler/rustc_target/src/spec/x86_64h_apple_darwin.rs rename to compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index 54f7490b2c05..a30e9d17cef8 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 96fed0975666..000000000000 --- 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 5ba29f878558..6fab9441bdc2 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 d655a4106b86..6eefccbde04c 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 377ae1b4e85f..5f08bc0039ae 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> 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> 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 b3f9218d7619..ae7f6ca2f7a0 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 70235b710e2b..583eb9f96a9d 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 240141065dcc..7fb550aa3e06 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 a0e2ad6e2027..84baec4ff4c1 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 8096d7969f39..dbf6749b5237 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 dcf5fd869290..787d80630058 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 5bc5a12a8fed..b246e476bedf 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 31da437f2e90..262bed8610c0 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 \ 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 ba2e3d1ae282..aa284cfc9c58 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 17c7f94ee883..3e5dd8c50d4a 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 e4f7592c409e..3bc401128b3a 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, mapped_types: BTreeMap, - mapped_consts: BTreeMap, ty::BoundVar>, + mapped_consts: BTreeMap, // 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, BTreeMap, - BTreeMap, ty::BoundVar>, + BTreeMap, ) { let mapped_regions: BTreeMap = BTreeMap::new(); let mapped_types: BTreeMap = BTreeMap::new(); - let mapped_consts: BTreeMap, ty::BoundVar> = BTreeMap::new(); + let mapped_consts: BTreeMap = BTreeMap::new(); let mut replacer = BoundVarReplacer { infcx, @@ -894,16 +894,16 @@ impl<'tcx> TypeFolder> 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, mapped_types: BTreeMap, - mapped_consts: BTreeMap, ty::BoundVar>, + mapped_consts: BTreeMap, universe_indices: &'me [Option], current_index: ty::DebruijnIndex, } @@ -976,7 +976,7 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> { infcx: &'me InferCtxt<'tcx>, mapped_regions: BTreeMap, mapped_types: BTreeMap, - mapped_consts: BTreeMap, ty::BoundVar>, + mapped_consts: BTreeMap, universe_indices: &'me [Option], value: T, ) -> T { @@ -1034,7 +1034,7 @@ impl<'tcx> TypeFolder> 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 2e31b560b38f..dba00ce0154b 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> for MaxEscapingBoundVarVisitor { #[inline] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { - ty::ReLateBound(debruijn, _) if debruijn > self.outer_index => { + ty::ReBound(debruijn, _) if debruijn > self.outer_index => { 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 5c67188dd240..c1d44601891b 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`, // but `Foo` is declared as `trait Foo: Bar`. - 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 4bfa341e3332..abb4e71a9af5 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 cf52e6726a17..1ed0da59b64f 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 fe5b625e4836..9751cb60ed89 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>, ) -> Vec> { - // 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 2563e3ed1a34..cb2a36cb998b 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 01bb1ca70eb4..b8c71bc96f88 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 fcf6626bbf05..38f2d616f9a5 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 283862b5e1cc..52f723eba80e 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 abf3e108ed48..2b262cfdebd3 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -195,7 +195,7 @@ impl<'tcx> TypeVisitor> 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> 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 c8e730b585ad..ace9eade7f69 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 { pub value: V, pub max_universe: UniverseIndex, @@ -127,27 +126,3 @@ where self.variables.visit_with(folder) } } - -impl, V: Encodable> Encodable for Canonical -where - I::CanonicalVars: Encodable, -{ - fn encode(&self, s: &mut E) { - self.value.encode(s); - self.max_universe.encode(s); - self.variables.encode(s); - } -} - -impl, V: Decodable> Decodable for Canonical -where - I::CanonicalVars: Decodable, -{ - 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 cf67ba0b21a1..33782b13ca8f 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 { /// A const generic parameter. Param(I::ParamConst), @@ -92,67 +89,6 @@ where } } -impl> Decodable for ConstKind -where - I::ParamConst: Decodable, - I::InferConst: Decodable, - I::BoundConst: Decodable, - I::PlaceholderConst: Decodable, - I::AliasConst: Decodable, - I::ValueConst: Decodable, - I::ErrorGuaranteed: Decodable, - I::ExprConst: Decodable, -{ - 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> Encodable for ConstKind -where - I::ParamConst: Encodable, - I::InferConst: Encodable, - I::BoundConst: Encodable, - I::PlaceholderConst: Encodable, - I::AliasConst: Encodable, - I::ValueConst: Encodable, - I::ErrorGuaranteed: Encodable, - I::ExprConst: Encodable, -{ - 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 PartialEq for ConstKind { 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 d5cadd4e83a7..d10927b0d939 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 a056fbeda981..e8785fff2efc 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 23117fdd5310..48662d426423 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 { /// Corresponds to `where Foo: Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` @@ -161,65 +159,9 @@ where } } -impl> Decodable for ClauseKind -where - I::Ty: Decodable, - I::Const: Decodable, - I::GenericArg: Decodable, - I::TraitPredicate: Decodable, - I::ProjectionPredicate: Decodable, - I::TypeOutlivesPredicate: Decodable, - I::RegionOutlivesPredicate: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => ClauseKind::Trait(Decodable::decode(d)), - 1 => ClauseKind::RegionOutlives(Decodable::decode(d)), - 2 => ClauseKind::TypeOutlives(Decodable::decode(d)), - 3 => ClauseKind::Projection(Decodable::decode(d)), - 4 => ClauseKind::ConstArgHasType(Decodable::decode(d), Decodable::decode(d)), - 5 => ClauseKind::WellFormed(Decodable::decode(d)), - 6 => ClauseKind::ConstEvaluatable(Decodable::decode(d)), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "ClauseKind", 7, - ) - ), - } - } -} - -impl Encodable for ClauseKind -where - I::Ty: Encodable, - I::Const: Encodable, - I::GenericArg: Encodable, - I::TraitPredicate: Encodable, - I::ProjectionPredicate: Encodable, - I::TypeOutlivesPredicate: Encodable, - I::RegionOutlivesPredicate: Encodable, -{ - fn encode(&self, s: &mut E) { - let discriminant = clause_kind_discriminant(self); - match self { - ClauseKind::Trait(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::RegionOutlives(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::TypeOutlives(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::Projection(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::ConstArgHasType(c, t) => s.emit_enum_variant(discriminant, |s| { - c.encode(s); - t.encode(s); - }), - ClauseKind::WellFormed(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - ClauseKind::ConstEvaluatable(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)), - } - } -} - #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Hash(bound = ""))] +#[derive(TyEncodable, TyDecodable)] pub enum PredicateKind { /// Prove a clause Clause(ClauseKind), @@ -418,83 +360,6 @@ where } } -impl> Decodable for PredicateKind -where - I::DefId: Decodable, - I::Const: Decodable, - I::GenericArgs: Decodable, - I::Term: Decodable, - I::CoercePredicate: Decodable, - I::SubtypePredicate: Decodable, - I::ClosureKind: Decodable, - ClauseKind: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => PredicateKind::Clause(Decodable::decode(d)), - 1 => PredicateKind::ObjectSafe(Decodable::decode(d)), - 2 => PredicateKind::ClosureKind( - Decodable::decode(d), - Decodable::decode(d), - Decodable::decode(d), - ), - 3 => PredicateKind::Subtype(Decodable::decode(d)), - 4 => PredicateKind::Coerce(Decodable::decode(d)), - 5 => PredicateKind::ConstEquate(Decodable::decode(d), Decodable::decode(d)), - 6 => PredicateKind::Ambiguous, - 7 => PredicateKind::AliasRelate( - Decodable::decode(d), - Decodable::decode(d), - Decodable::decode(d), - ), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "PredicateKind", 8, - ) - ), - } - } -} - -impl Encodable for PredicateKind -where - I::DefId: Encodable, - I::Const: Encodable, - I::GenericArgs: Encodable, - I::Term: Encodable, - I::CoercePredicate: Encodable, - I::SubtypePredicate: Encodable, - I::ClosureKind: Encodable, - ClauseKind: Encodable, -{ - fn encode(&self, s: &mut E) { - let discriminant = predicate_kind_discriminant(self); - match self { - PredicateKind::Clause(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)), - PredicateKind::ObjectSafe(d) => s.emit_enum_variant(discriminant, |s| d.encode(s)), - PredicateKind::ClosureKind(d, g, k) => s.emit_enum_variant(discriminant, |s| { - d.encode(s); - g.encode(s); - k.encode(s); - }), - PredicateKind::Subtype(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)), - PredicateKind::Coerce(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)), - PredicateKind::ConstEquate(a, b) => s.emit_enum_variant(discriminant, |s| { - a.encode(s); - b.encode(s); - }), - PredicateKind::Ambiguous => s.emit_enum_variant(discriminant, |_s| {}), - PredicateKind::AliasRelate(a, b, d) => s.emit_enum_variant(discriminant, |s| { - a.encode(s); - b.encode(s); - d.encode(s); - }), - } - } -} - #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] #[derive(HashStable_Generic, Encodable, Decodable)] pub enum AliasRelationDirection { diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 72f86fc06929..fc9eaf63ac82 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 { /// 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 { const fn regionkind_discriminant(value: &RegionKind) -> usize { match value { ReEarlyBound(_) => 0, - ReLateBound(_, _) => 1, + ReBound(_, _) => 1, ReFree(_) => 2, ReStatic => 3, ReVar(_) => 4, @@ -192,7 +196,7 @@ impl PartialEq for RegionKind { 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 DebugWithInfcx for RegionKind { 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 fmt::Debug for RegionKind { } } -// This is manually implemented because a derive would require `I: Encodable` -impl> Encodable for RegionKind -where - I::EarlyBoundRegion: Encodable, - I::BoundRegion: Encodable, - I::FreeRegion: Encodable, - I::InferRegion: Encodable, - I::PlaceholderRegion: Encodable, -{ - fn encode(&self, e: &mut E) { - let disc = regionkind_discriminant(self); - match self { - ReEarlyBound(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - ReLateBound(a, b) => e.emit_enum_variant(disc, |e| { - a.encode(e); - b.encode(e); - }), - ReFree(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - ReStatic => e.emit_enum_variant(disc, |_| {}), - ReVar(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - RePlaceholder(a) => e.emit_enum_variant(disc, |e| { - a.encode(e); - }), - ReErased => e.emit_enum_variant(disc, |_| {}), - ReError(_) => e.emit_enum_variant(disc, |_| {}), - } - } -} - -// This is manually implemented because a derive would require `I: Decodable` -impl> Decodable for RegionKind -where - I::EarlyBoundRegion: Decodable, - I::BoundRegion: Decodable, - I::FreeRegion: Decodable, - I::InferRegion: Decodable, - I::PlaceholderRegion: Decodable, - I::ErrorGuaranteed: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => ReEarlyBound(Decodable::decode(d)), - 1 => ReLateBound(Decodable::decode(d), Decodable::decode(d)), - 2 => ReFree(Decodable::decode(d)), - 3 => ReStatic, - 4 => ReVar(Decodable::decode(d)), - 5 => RePlaceholder(Decodable::decode(d)), - 6 => ReErased, - 7 => ReError(Decodable::decode(d)), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "RegionKind", 8, - ) - ), - } - } -} - // This is not a derived impl because a derive would require `I: HashStable` impl HashStable for RegionKind 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 2138c2733413..09a9a332269e 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 { /// The primitive boolean type. Written as `bool`. Bool, @@ -472,178 +470,6 @@ impl fmt::Debug for TyKind { } } -// This is manually implemented because a derive would require `I: Encodable` -impl> Encodable for TyKind -where - I::ErrorGuaranteed: Encodable, - I::AdtDef: Encodable, - I::GenericArgs: Encodable, - I::DefId: Encodable, - I::Ty: Encodable, - I::Const: Encodable, - I::Region: Encodable, - I::TypeAndMut: Encodable, - I::PolyFnSig: Encodable, - I::BoundExistentialPredicates: Encodable, - I::Tys: Encodable, - I::AliasTy: Encodable, - I::ParamTy: Encodable, - I::BoundTy: Encodable, - I::PlaceholderTy: Encodable, - I::InferTy: Encodable, - I::AllocId: Encodable, -{ - fn encode(&self, e: &mut E) { - let disc = tykind_discriminant(self); - match self { - Bool => e.emit_enum_variant(disc, |_| {}), - Char => e.emit_enum_variant(disc, |_| {}), - Int(i) => e.emit_enum_variant(disc, |e| { - i.encode(e); - }), - Uint(u) => e.emit_enum_variant(disc, |e| { - u.encode(e); - }), - Float(f) => e.emit_enum_variant(disc, |e| { - f.encode(e); - }), - Adt(adt, args) => e.emit_enum_variant(disc, |e| { - adt.encode(e); - args.encode(e); - }), - Foreign(def_id) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - }), - Str => e.emit_enum_variant(disc, |_| {}), - Array(t, c) => e.emit_enum_variant(disc, |e| { - t.encode(e); - c.encode(e); - }), - Slice(t) => e.emit_enum_variant(disc, |e| { - t.encode(e); - }), - RawPtr(tam) => e.emit_enum_variant(disc, |e| { - tam.encode(e); - }), - Ref(r, t, m) => e.emit_enum_variant(disc, |e| { - r.encode(e); - t.encode(e); - m.encode(e); - }), - FnDef(def_id, args) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - }), - FnPtr(polyfnsig) => e.emit_enum_variant(disc, |e| { - polyfnsig.encode(e); - }), - Dynamic(l, r, repr) => e.emit_enum_variant(disc, |e| { - l.encode(e); - r.encode(e); - repr.encode(e); - }), - Closure(def_id, args) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - }), - Coroutine(def_id, args, m) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - m.encode(e); - }), - CoroutineWitness(def_id, args) => e.emit_enum_variant(disc, |e| { - def_id.encode(e); - args.encode(e); - }), - Never => e.emit_enum_variant(disc, |_| {}), - Tuple(args) => e.emit_enum_variant(disc, |e| { - args.encode(e); - }), - Alias(k, p) => e.emit_enum_variant(disc, |e| { - k.encode(e); - p.encode(e); - }), - Param(p) => e.emit_enum_variant(disc, |e| { - p.encode(e); - }), - Bound(d, b) => e.emit_enum_variant(disc, |e| { - d.encode(e); - b.encode(e); - }), - Placeholder(p) => e.emit_enum_variant(disc, |e| { - p.encode(e); - }), - Infer(i) => e.emit_enum_variant(disc, |e| { - i.encode(e); - }), - Error(d) => e.emit_enum_variant(disc, |e| { - d.encode(e); - }), - } - } -} - -// This is manually implemented because a derive would require `I: Decodable` -impl> Decodable for TyKind -where - I::ErrorGuaranteed: Decodable, - I::AdtDef: Decodable, - I::GenericArgs: Decodable, - I::DefId: Decodable, - I::Ty: Decodable, - I::Const: Decodable, - I::Region: Decodable, - I::TypeAndMut: Decodable, - I::PolyFnSig: Decodable, - I::BoundExistentialPredicates: Decodable, - I::Tys: Decodable, - I::AliasTy: Decodable, - I::ParamTy: Decodable, - I::AliasTy: Decodable, - I::BoundTy: Decodable, - I::PlaceholderTy: Decodable, - I::InferTy: Decodable, - I::AllocId: Decodable, -{ - fn decode(d: &mut D) -> Self { - match Decoder::read_usize(d) { - 0 => Bool, - 1 => Char, - 2 => Int(Decodable::decode(d)), - 3 => Uint(Decodable::decode(d)), - 4 => Float(Decodable::decode(d)), - 5 => Adt(Decodable::decode(d), Decodable::decode(d)), - 6 => Foreign(Decodable::decode(d)), - 7 => Str, - 8 => Array(Decodable::decode(d), Decodable::decode(d)), - 9 => Slice(Decodable::decode(d)), - 10 => RawPtr(Decodable::decode(d)), - 11 => Ref(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), - 12 => FnDef(Decodable::decode(d), Decodable::decode(d)), - 13 => FnPtr(Decodable::decode(d)), - 14 => Dynamic(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), - 15 => Closure(Decodable::decode(d), Decodable::decode(d)), - 16 => Coroutine(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), - 17 => CoroutineWitness(Decodable::decode(d), Decodable::decode(d)), - 18 => Never, - 19 => Tuple(Decodable::decode(d)), - 20 => Alias(Decodable::decode(d), Decodable::decode(d)), - 21 => Param(Decodable::decode(d)), - 22 => Bound(Decodable::decode(d), Decodable::decode(d)), - 23 => Placeholder(Decodable::decode(d)), - 24 => Infer(Decodable::decode(d)), - 25 => Error(Decodable::decode(d)), - _ => panic!( - "{}", - format!( - "invalid enum variant tag while decoding `{}`, expected 0..{}", - "TyKind", 26, - ) - ), - } - } -} - // This is not a derived impl because a derive would require `I: HashStable` #[allow(rustc::usage_of_ty_tykind)] impl HashStable for TyKind diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 4818bceadeff..069337836853 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 5dfaa0fd8915..d2f1f3af0cef 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), ReErased, @@ -156,6 +156,7 @@ pub enum RigidTy { Dynamic(Vec>, Region, DynKind), Never, Tuple(Vec), + 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); diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs index 05e0b9b4d786..65e42879d618 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 66fa91d4bad1..e5df28a49af6 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 1e2c35bf735f..5b50ef7bf6c2 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 4f0a02da4407..f07c76232ebc 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 bd66ad612196..817b93720ce2 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -305,10 +305,13 @@ impl RawVec { /// The same as `reserve`, but returns on errors instead of panicking or aborting. pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { if self.needs_to_grow(len, additional) { - self.grow_amortized(len, additional) - } else { - Ok(()) + self.grow_amortized(len, additional)?; } + unsafe { + // Inform the optimizer that the reservation has succeeded or wasn't needed + core::intrinsics::assume(!self.needs_to_grow(len, additional)); + } + Ok(()) } /// Ensures that the buffer contains at least enough space to hold `len + @@ -339,7 +342,14 @@ impl RawVec { len: usize, additional: usize, ) -> Result<(), TryReserveError> { - if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) } + if self.needs_to_grow(len, additional) { + self.grow_exact(len, additional)?; + } + unsafe { + // Inform the optimizer that the reservation has succeeded or wasn't needed + core::intrinsics::assume(!self.needs_to_grow(len, additional)); + } + Ok(()) } /// Shrinks the buffer down to the specified capacity. If the given amount diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6c78d65f1c94..ea7d6f6f4a64 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2706,7 +2706,7 @@ impl Clone for Vec { /// ``` /// use std::hash::BuildHasher; /// -/// let b = std::collections::hash_map::RandomState::new(); +/// let b = std::hash::RandomState::new(); /// let v: Vec = vec![0xa8, 0x3c, 0x09]; /// let s: &[u8] = &[0xa8, 0x3c, 0x09]; /// assert_eq!(b.hash_one(v), b.hash_one(s)); diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index aa7a331b368b..6d5c17ef0230 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 ebd4a8c05fe3..9c8d7bbd9997 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 89125b7955e0..8c01b0973d65 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -138,7 +138,7 @@ pub const fn identity(x: T) -> T { /// /// [dereferenceable types]: core::ops::Deref /// [pointed-to value]: core::ops::Deref::Target -/// ['`Deref` coercion']: core::ops::Deref#more-on-deref-coercion +/// ['`Deref` coercion']: core::ops::Deref#deref-coercion /// /// ``` /// let x = Box::new(5i32); @@ -244,7 +244,7 @@ pub trait AsRef { /// /// [mutably dereferenceable types]: core::ops::DerefMut /// [pointed-to value]: core::ops::Deref::Target -/// ['`Deref` coercion']: core::ops::DerefMut#more-on-deref-coercion +/// ['`Deref` coercion']: core::ops::DerefMut#mutable-deref-coercion /// /// ``` /// let mut x = Box::new(5i32); diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 1170221c10c4..f1a7ad935480 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -439,10 +439,10 @@ where /// * A Producer initializes the value of one of its fields of a specific type. (or is otherwise /// prepared to generate a value requested). eg, `backtrace::Backtrace` or /// `std::backtrace::Backtrace` -/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace). In the case -/// of a `dyn Error` trait object (the Producer), there are methods called `request_ref` and -/// `request_value` are available to simplify obtaining an ``Option`` for a given type. * The -/// Producer, when requested, populates the given Request object which is given as a mutable +/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace`). In the +/// case of a `dyn Error` trait object (the Producer), there are functions called `request_ref` and +/// `request_value` to simplify obtaining an `Option` for a given type. +/// * The Producer, when requested, populates the given Request object which is given as a mutable /// reference. /// * The Consumer extracts a value or reference to the requested type from the `Request` object /// wrapped in an `Option`; in the case of `dyn Error` the aforementioned `request_ref` and ` diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 47db53ac6f34..4ccb585862cd 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -130,6 +130,18 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self { + self.field_with(name, |f| value.fmt(f)) + } + + /// Adds a new field to the generated struct output. + /// + /// This method is equivalent to [`DebugStruct::field`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn field_with(&mut self, name: &str, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { if self.is_pretty() { if !self.has_fields { @@ -140,14 +152,14 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); writer.write_str(name)?; writer.write_str(": ")?; - value.fmt(&mut writer)?; + value_fmt(&mut writer)?; writer.write_str(",\n") } else { let prefix = if self.has_fields { ", " } else { " { " }; self.fmt.write_str(prefix)?; self.fmt.write_str(name)?; self.fmt.write_str(": ")?; - value.fmt(self.fmt) + value_fmt(self.fmt) } }); @@ -315,6 +327,18 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self { + self.field_with(|f| value.fmt(f)) + } + + /// Adds a new field to the generated tuple struct output. + /// + /// This method is equivalent to [`DebugTuple::field`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn field_with(&mut self, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { if self.is_pretty() { if self.fields == 0 { @@ -323,12 +347,12 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { let mut slot = None; let mut state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); - value.fmt(&mut writer)?; + value_fmt(&mut writer)?; writer.write_str(",\n") } else { let prefix = if self.fields == 0 { "(" } else { ", " }; self.fmt.write_str(prefix)?; - value.fmt(self.fmt) + value_fmt(self.fmt) } }); @@ -385,7 +409,10 @@ struct DebugInner<'a, 'b: 'a> { } impl<'a, 'b: 'a> DebugInner<'a, 'b> { - fn entry(&mut self, entry: &dyn fmt::Debug) { + fn entry_with(&mut self, entry_fmt: F) + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { if self.is_pretty() { if !self.has_fields { @@ -394,13 +421,13 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { let mut slot = None; let mut state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); - entry.fmt(&mut writer)?; + entry_fmt(&mut writer)?; writer.write_str(",\n") } else { if self.has_fields { self.fmt.write_str(", ")? } - entry.fmt(self.fmt) + entry_fmt(self.fmt) } }); @@ -475,7 +502,20 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { - self.inner.entry(entry); + self.inner.entry_with(|f| entry.fmt(f)); + self + } + + /// Adds a new entry to the set output. + /// + /// This method is equivalent to [`DebugSet::entry`], but formats the + /// entry using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.inner.entry_with(entry_fmt); self } @@ -605,7 +645,20 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { - self.inner.entry(entry); + self.inner.entry_with(|f| entry.fmt(f)); + self + } + + /// Adds a new entry to the list output. + /// + /// This method is equivalent to [`DebugList::entry`], but formats the + /// entry using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.inner.entry_with(entry_fmt); self } @@ -775,6 +828,18 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self { + self.key_with(|f| key.fmt(f)) + } + + /// Adds the key part of a new entry to the map output. + /// + /// This method is equivalent to [`DebugMap::key`], but formats the + /// key using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn key_with(&mut self, key_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { assert!( !self.has_key, @@ -789,13 +854,13 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { let mut slot = None; self.state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state); - key.fmt(&mut writer)?; + key_fmt(&mut writer)?; writer.write_str(": ")?; } else { if self.has_fields { self.fmt.write_str(", ")? } - key.fmt(self.fmt)?; + key_fmt(self.fmt)?; self.fmt.write_str(": ")?; } @@ -839,16 +904,28 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self { + self.value_with(|f| value.fmt(f)) + } + + /// Adds the value part of a new entry to the map output. + /// + /// This method is equivalent to [`DebugMap::value`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn value_with(&mut self, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { self.result = self.result.and_then(|_| { assert!(self.has_key, "attempted to format a map value before its key"); if self.is_pretty() { let mut slot = None; let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state); - value.fmt(&mut writer)?; + value_fmt(&mut writer)?; writer.write_str(",\n")?; } else { - value.fmt(self.fmt)?; + value_fmt(self.fmt)?; } self.has_key = false; @@ -936,3 +1013,44 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { self.fmt.alternate() } } + +/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function. +/// +/// # Examples +/// +/// ``` +/// #![feature(debug_closure_helpers)] +/// use std::fmt; +/// +/// let value = 'a'; +/// assert_eq!(format!("{}", value), "a"); +/// assert_eq!(format!("{:?}", value), "'a'"); +/// +/// let wrapped = fmt::FormatterFn(|f| write!(f, "{:?}", &value)); +/// assert_eq!(format!("{}", wrapped), "'a'"); +/// assert_eq!(format!("{:?}", wrapped), "'a'"); +/// ``` +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub struct FormatterFn(pub F) +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result; + +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +impl fmt::Debug for FormatterFn +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(f) + } +} + +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +impl fmt::Display for FormatterFn +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(f) + } +} diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index c45ab094a20d..e1b7b46a1ed2 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 4f42f73ebbaf..778515f8616c 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 35b757dc1ee0..153971a59c5c 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -12,8 +12,7 @@ //! # Examples //! //! ```rust -//! use std::collections::hash_map::DefaultHasher; -//! use std::hash::{Hash, Hasher}; +//! use std::hash::{DefaultHasher, Hash, Hasher}; //! //! #[derive(Hash)] //! struct Person { @@ -46,8 +45,7 @@ //! the [`Hash`] trait: //! //! ```rust -//! use std::collections::hash_map::DefaultHasher; -//! use std::hash::{Hash, Hasher}; +//! use std::hash::{DefaultHasher, Hash, Hasher}; //! //! struct Person { //! id: u32, @@ -194,8 +192,7 @@ pub trait Hash { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::{Hash, Hasher}; + /// use std::hash::{DefaultHasher, Hash, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// 7920.hash(&mut hasher); @@ -224,8 +221,7 @@ pub trait Hash { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::{Hash, Hasher}; + /// use std::hash::{DefaultHasher, Hash, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// let numbers = [6, 28, 496, 8128]; @@ -300,8 +296,7 @@ pub use macros::Hash; /// # Examples /// /// ``` -/// use std::collections::hash_map::DefaultHasher; -/// use std::hash::Hasher; +/// use std::hash::{DefaultHasher, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// @@ -329,8 +324,7 @@ pub trait Hasher { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::Hasher; + /// use std::hash::{DefaultHasher, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// hasher.write(b"Cool!"); @@ -347,8 +341,7 @@ pub trait Hasher { /// # Examples /// /// ``` - /// use std::collections::hash_map::DefaultHasher; - /// use std::hash::Hasher; + /// use std::hash::{DefaultHasher, Hasher}; /// /// let mut hasher = DefaultHasher::new(); /// let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]; @@ -627,8 +620,7 @@ impl Hasher for &mut H { /// # Examples /// /// ``` -/// use std::collections::hash_map::RandomState; -/// use std::hash::{BuildHasher, Hasher}; +/// use std::hash::{BuildHasher, Hasher, RandomState}; /// /// let s = RandomState::new(); /// let mut hasher_1 = s.build_hasher(); @@ -656,8 +648,7 @@ pub trait BuildHasher { /// # Examples /// /// ``` - /// use std::collections::hash_map::RandomState; - /// use std::hash::BuildHasher; + /// use std::hash::{BuildHasher, RandomState}; /// /// let s = RandomState::new(); /// let new_s = s.build_hasher(); @@ -690,7 +681,7 @@ pub trait BuildHasher { /// } /// /// // Then later, in a `#[test]` for the type... - /// let bh = std::collections::hash_map::RandomState::new(); + /// let bh = std::hash::RandomState::new(); /// assert_eq!( /// bh.hash_one(OrderAmbivalentPair(1, 2)), /// bh.hash_one(OrderAmbivalentPair(2, 1)) diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs index 6b9f2e84257d..78a232faaf88 100644 --- a/library/core/src/hash/sip.rs +++ b/library/core/src/hash/sip.rs @@ -14,7 +14,7 @@ use crate::ptr; /// /// See: #[unstable(feature = "hashmap_internals", issue = "none")] -#[deprecated(since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] #[doc(hidden)] pub struct SipHasher13 { @@ -25,7 +25,7 @@ pub struct SipHasher13 { /// /// See: #[unstable(feature = "hashmap_internals", issue = "none")] -#[deprecated(since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] struct SipHasher24 { hasher: Hasher, @@ -44,7 +44,7 @@ struct SipHasher24 { /// it is not intended for cryptographic purposes. As such, all /// cryptographic uses of this implementation are _strongly discouraged_. #[stable(feature = "rust1", since = "1.0.0")] -#[deprecated(since = "1.13.0", note = "use `std::collections::hash_map::DefaultHasher` instead")] +#[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher(SipHasher24); @@ -147,10 +147,7 @@ impl SipHasher { /// Creates a new `SipHasher` with the two initial keys set to 0. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] pub const fn new() -> SipHasher { @@ -160,10 +157,7 @@ impl SipHasher { /// Creates a `SipHasher` that is keyed off the provided keys. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher { @@ -175,10 +169,7 @@ impl SipHasher13 { /// Creates a new `SipHasher13` with the two initial keys set to 0. #[inline] #[unstable(feature = "hashmap_internals", issue = "none")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] pub const fn new() -> SipHasher13 { SipHasher13::new_with_keys(0, 0) @@ -187,10 +178,7 @@ impl SipHasher13 { /// Creates a `SipHasher13` that is keyed off the provided keys. #[inline] #[unstable(feature = "hashmap_internals", issue = "none")] - #[deprecated( - since = "1.13.0", - note = "use `std::collections::hash_map::DefaultHasher` instead" - )] + #[deprecated(since = "1.13.0", note = "use `std::hash::DefaultHasher` instead")] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] pub const fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 964aa3906f1d..f855b2ad4833 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(); @@ -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(); diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index b26a17ec30e9..0d8a306ace5e 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(place: T, goto: BasicBlock)); -define!("mir_call", fn Call(call: (), goto: BasicBlock)); +define!("mir_drop", fn Drop(place: T, goto: BasicBlock, unwind_action: U)); +define!("mir_call", fn Call(call: (), goto: BasicBlock, unwind_action: U)); +define!("mir_unwind_resume", + /// A terminator that resumes the unwinding. + fn UnwindResume() +); + define!("mir_storage_live", fn StorageLive(local: T)); define!("mir_storage_dead", fn StorageDead(local: T)); define!("mir_deinit", fn Deinit(place: T)); @@ -382,16 +427,15 @@ pub macro mir { } $( - $block_name:ident = { + $block_name:ident $(($block_cleanup:ident))? = { $($block:tt)* } )* ) => {{ // First, we declare all basic blocks. - $( - let $block_name: ::core::intrinsics::mir::BasicBlock; - )* - + __internal_declare_basic_blocks!($( + $block_name $(($block_cleanup))? + )*); { // Now all locals #[allow(non_snake_case)] @@ -585,3 +629,17 @@ pub macro __internal_remove_let { } }, } + +/// Helper macro that declares the basic blocks. +#[doc(hidden)] +pub macro __internal_declare_basic_blocks { + () => {}, + ($name:ident (cleanup) $($rest:tt)*) => { + let $name = ::core::intrinsics::mir::BasicBlock::Cleanup; + __internal_declare_basic_blocks!($($rest)*) + }, + ($name:ident $($rest:tt)*) => { + let $name = ::core::intrinsics::mir::BasicBlock::Normal; + __internal_declare_basic_blocks!($($rest)*) + }, +} diff --git a/library/std/src/io/readbuf.rs b/library/core/src/io/borrowed_buf.rs similarity index 97% rename from library/std/src/io/readbuf.rs rename to library/core/src/io/borrowed_buf.rs index 034ddd8df9ae..fe25cac280fe 100644 --- a/library/std/src/io/readbuf.rs +++ b/library/core/src/io/borrowed_buf.rs @@ -1,10 +1,6 @@ -#![unstable(feature = "read_buf", issue = "78485")] - -#[cfg(test)] -mod tests; +#![unstable(feature = "core_io_borrowed_buf", issue = "117693")] use crate::fmt::{self, Debug, Formatter}; -use crate::io::{Result, Write}; use crate::mem::{self, MaybeUninit}; use crate::{cmp, ptr}; @@ -303,15 +299,3 @@ impl<'a> BorrowedCursor<'a> { self.buf.filled += buf.len(); } } - -impl<'a> Write for BorrowedCursor<'a> { - fn write(&mut self, buf: &[u8]) -> Result { - self.append(buf); - Ok(buf.len()) - } - - #[inline] - fn flush(&mut self) -> Result<()> { - Ok(()) - } -} diff --git a/library/core/src/io/mod.rs b/library/core/src/io/mod.rs new file mode 100644 index 000000000000..2f20180cdc9a --- /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 de643fb333ef..5a6d242a7298 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 125a6f57bfba..7f5908e477cf 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 13437d8f9612..99762bccd18f 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -253,6 +253,7 @@ marker_impls! { /// /// const CFN: Wrap = Wrap(higher_order); /// +/// #[allow(pointer_structural_match)] /// fn main() { /// match CFN { /// CFN => {} diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 855bb1675c59..8a4070ebd96b 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -374,6 +374,9 @@ impl MaybeUninit { /// assert_eq!(x, (0, false)); /// ``` /// + /// This can be used in const contexts, such as to indicate the end of static arrays for + /// plugin registration. + /// /// *Incorrect* usage of this function: calling `x.zeroed().assume_init()` /// when `0` is not a valid bit-pattern for the type: /// @@ -387,17 +390,19 @@ impl MaybeUninit { /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. /// // This is undefined behavior. ⚠️ /// ``` - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_unstable(feature = "const_maybe_uninit_zeroed", issue = "91850")] - #[must_use] #[inline] + #[must_use] #[rustc_diagnostic_item = "maybe_uninit_zeroed"] + #[stable(feature = "maybe_uninit", since = "1.36.0")] + // These are OK to allow since we do not leak &mut to user-visible API + #[rustc_allow_const_fn_unstable(const_mut_refs)] + #[rustc_allow_const_fn_unstable(const_ptr_write)] + #[rustc_allow_const_fn_unstable(const_maybe_uninit_as_mut_ptr)] + #[rustc_const_stable(feature = "const_maybe_uninit_zeroed", since = "CURRENT_RUSTC_VERSION")] pub const fn zeroed() -> MaybeUninit { let mut u = MaybeUninit::::uninit(); // SAFETY: `u.as_mut_ptr()` points to allocated memory. - unsafe { - u.as_mut_ptr().write_bytes(0u8, 1); - } + unsafe { u.as_mut_ptr().write_bytes(0u8, 1) }; u } diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 9159ecb740d9..c964596dd5fe 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -647,7 +647,8 @@ pub const fn needs_drop() -> bool { #[allow(deprecated)] #[rustc_diagnostic_item = "mem_zeroed"] #[track_caller] -pub unsafe fn zeroed() -> T { +#[rustc_const_stable(feature = "const_mem_zeroed", since = "CURRENT_RUSTC_VERSION")] +pub const unsafe fn zeroed() -> T { // SAFETY: the caller must guarantee that an all-zero value is valid for `T`. unsafe { intrinsics::assert_zero_valid::(); @@ -1357,6 +1358,7 @@ impl 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 d6f2f5ca3662..99adbb91599a 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -3,40 +3,107 @@ /// In addition to being used for explicit dereferencing operations with the /// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly /// by the compiler in many circumstances. This mechanism is called -/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used. +/// ["`Deref` coercion"][coercion]. In mutable contexts, [`DerefMut`] is used and +/// mutable deref coercion similarly occurs. /// -/// Implementing `Deref` for smart pointers makes accessing the data behind them -/// convenient, which is why they implement `Deref`. On the other hand, the -/// rules regarding `Deref` and [`DerefMut`] were designed specifically to -/// accommodate smart pointers. Because of this, **`Deref` should only be -/// implemented for smart pointers** to avoid confusion. +/// **Warning:** Deref coercion is a powerful language feature which has +/// far-reaching implications for every type that implements `Deref`. The +/// compiler will silently insert calls to `Deref::deref`. For this reason, one +/// should be careful about implementing `Deref` and only do so when deref +/// coercion is desirable. See [below][implementing] for advice on when this is +/// typically desirable or undesirable. /// -/// For similar reasons, **this trait should never fail**. Failure during -/// dereferencing can be extremely confusing when `Deref` is invoked implicitly. +/// Types that implement `Deref` or `DerefMut` are often called "smart +/// pointers" and the mechanism of deref coercion has been specifically designed +/// to facilitate the pointer-like behaviour that name suggests. Often, the +/// purpose of a "smart pointer" type is to change the ownership semantics +/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the +/// storage semantics of a contained value (for example, [`Box`][box]). /// -/// Violating these requirements is a logic error. The behavior resulting from a logic error is not -/// specified, but users of the trait must ensure that such logic errors do *not* result in -/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this -/// method. +/// # Deref coercion /// -/// # More on `Deref` coercion +/// If `T` implements `Deref`, and `v` is a value of type `T`, then: /// -/// If `T` implements `Deref`, and `x` is a value of type `T`, then: -/// -/// * In immutable contexts, `*x` (where `T` is neither a reference nor a raw pointer) -/// is equivalent to `*Deref::deref(&x)`. +/// * In immutable contexts, `*v` (where `T` is neither a reference nor a raw +/// pointer) is equivalent to `*Deref::deref(&v)`. /// * Values of type `&T` are coerced to values of type `&U` -/// * `T` implicitly implements all the (immutable) methods of the type `U`. +/// * `T` implicitly implements all the methods of the type `U` which take the +/// `&self` receiver. /// /// For more details, visit [the chapter in *The Rust Programming Language*][book] /// as well as the reference sections on [the dereference operator][ref-deref-op], -/// [method resolution] and [type coercions]. +/// [method resolution], and [type coercions]. +/// +/// # When to implement `Deref` or `DerefMut` +/// +/// The same advice applies to both deref traits. In general, deref traits +/// **should** be implemented if: +/// +/// 1. a value of the type transparently behaves like a value of the target +/// type; +/// 1. the implementation of the deref function is cheap; and +/// 1. users of the type will not be surprised by any deref coercion behaviour. +/// +/// In general, deref traits **should not** be implemented if: +/// +/// 1. the deref implementations could fail unexpectedly; or +/// 1. the type has methods that are likely to collide with methods on the +/// target type; or +/// 1. committing to deref coercion as part of the public API is not desirable. +/// +/// Note that there's a large difference between implementing deref traits +/// generically over many target types, and doing so only for specific target +/// types. +/// +/// Generic implementations, such as for [`Box`][box] (which is generic over +/// every type and dereferences to `T`) should be careful to provide few or no +/// methods, since the target type is unknown and therefore every method could +/// collide with one on the target type, causing confusion for users. +/// `impl Box` has no methods (though several associated functions), +/// partly for this reason. +/// +/// Specific implementations, such as for [`String`][string] (whose `Deref` +/// implementation has `Target = str`) can have many methods, since avoiding +/// collision is much easier. `String` and `str` both have many methods, and +/// `String` additionally behaves as if it has every method of `str` because of +/// deref coercion. The implementing type may also be generic while the +/// implementation is still specific in this sense; for example, [`Vec`][vec] +/// dereferences to `[T]`, so methods of `T` are not applicable. +/// +/// Consider also that deref coericion means that deref traits are a much larger +/// part of a type's public API than any other trait as it is implicitly called +/// by the compiler. Therefore, it is advisable to consider whether this is +/// something you are comfortable supporting as a public API. +/// +/// The [`AsRef`] and [`Borrow`][core::borrow::Borrow] traits have very similar +/// signatures to `Deref`. It may be desirable to implement either or both of +/// these, whether in addition to or rather than deref traits. See their +/// documentation for details. +/// +/// # Fallibility +/// +/// **This trait's method should never unexpectedly fail**. Deref coercion means +/// the compiler will often insert calls to `Deref::deref` implicitly. Failure +/// during dereferencing can be extremely confusing when `Deref` is invoked +/// implicitly. In the majority of uses it should be infallible, though it may +/// be acceptable to panic if the type is misused through programmer error, for +/// example. +/// +/// However, infallibility is not enforced and therefore not guaranteed. +/// As such, `unsafe` code should not rely on infallibility in general for +/// soundness. /// /// [book]: ../../book/ch15-02-deref.html -/// [more]: #more-on-deref-coercion +/// [coercion]: #deref-coercion +/// [implementing]: #when-to-implement-deref-or-derefmut /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator /// [method resolution]: ../../reference/expressions/method-call-expr.html /// [type coercions]: ../../reference/type-coercions.html +/// [box]: ../../alloc/boxed/struct.Box.html +/// [string]: ../../alloc/string/struct.String.html +/// [vec]: ../../alloc/vec/struct.Vec.html +/// [rc]: ../../alloc/rc/struct.Rc.html +/// [cow]: ../../alloc/borrow/enum.Cow.html /// /// # Examples /// @@ -107,30 +174,29 @@ impl Deref for &mut T { /// In addition to being used for explicit dereferencing operations with the /// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly /// by the compiler in many circumstances. This mechanism is called -/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used. +/// ["mutable deref coercion"][coercion]. 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. +/// **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. /// -/// For similar reasons, **this trait should never fail**. Failure during -/// dereferencing can be extremely confusing when `DerefMut` is invoked -/// implicitly. +/// 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]). /// -/// 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. +/// # Mutable deref coercion /// -/// # More on `Deref` coercion -/// -/// If `T` implements `DerefMut`, and `x` is a value of type `T`, +/// If `T` implements `DerefMut`, and `v` is a value of type `T`, /// then: /// -/// * In mutable contexts, `*x` (where `T` is neither a reference nor a raw pointer) -/// is equivalent to `*DerefMut::deref_mut(&mut x)`. +/// * In mutable contexts, `*v` (where `T` is neither a reference nor a raw pointer) +/// is equivalent to `*DerefMut::deref_mut(&mut v)`. /// * Values of type `&mut T` are coerced to values of type `&mut U` /// * `T` implicitly implements all the (mutable) methods of the type `U`. /// @@ -138,11 +204,29 @@ impl Deref for &mut T { /// as well as the reference sections on [the dereference operator][ref-deref-op], /// [method resolution] and [type coercions]. /// +/// # Fallibility +/// +/// **This trait's method should never unexpectedly fail**. Deref coercion means +/// the compiler will often insert calls to `DerefMut::deref_mut` implicitly. +/// Failure during dereferencing can be extremely confusing when `DerefMut` is +/// invoked implicitly. In the majority of uses it should be infallible, though +/// it may be acceptable to panic if the type is misused through programmer +/// error, for example. +/// +/// However, infallibility is not enforced and therefore not guaranteed. +/// As such, `unsafe` code should not rely on infallibility in general for +/// soundness. +/// /// [book]: ../../book/ch15-02-deref.html -/// [more]: #more-on-deref-coercion +/// [coercion]: #mutable-deref-coercion +/// [implementing]: Deref#when-to-implement-deref-or-derefmut /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator /// [method resolution]: ../../reference/expressions/method-call-expr.html /// [type coercions]: ../../reference/type-coercions.html +/// [box]: ../../alloc/boxed/struct.Box.html +/// [string]: ../../alloc/string/struct.String.html +/// [rc]: ../../alloc/rc/struct.Rc.html +/// [cow]: ../../alloc/borrow/enum.Cow.html /// /// # Examples /// diff --git a/library/core/src/option.rs b/library/core/src/option.rs index acf3dfbdf4cf..2303f289cdd6 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1079,8 +1079,6 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// let v = vec![1, 2, 3, 4, 5]; /// /// // prints "got: 4" @@ -1090,11 +1088,8 @@ impl Option { /// let x: Option<&usize> = v.get(5).inspect(|x| println!("got: {x}")); /// ``` #[inline] - #[unstable(feature = "result_option_inspect", issue = "91345")] - pub fn inspect(self, f: F) -> Self - where - F: FnOnce(&T), - { + #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] + pub fn inspect(self, f: F) -> Self { if let Some(ref x) = self { f(x); } diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index f3695d16d7a6..87e492108749 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -283,7 +283,7 @@ mod prim_never {} /// `char` type. For technical reasons, there is additional, separate /// documentation in [the `std::char` module](char/index.html) as well. /// -/// # Validity +/// # Validity and Layout /// /// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]' /// other than a [surrogate code point]. This has a fixed numerical definition: @@ -291,7 +291,7 @@ mod prim_never {} /// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF. /// /// No `char` may be constructed, whether as a literal or at runtime, that is not a -/// Unicode scalar value: +/// Unicode scalar value. Violating this rule causes undefined behavior. /// /// ```compile_fail /// // Each of these is a compiler error @@ -308,9 +308,10 @@ mod prim_never {} /// let _ = unsafe { char::from_u32_unchecked(0x110000) }; /// ``` /// -/// USVs are also the exact set of values that may be encoded in UTF-8. Because -/// `char` values are USVs and `str` values are valid UTF-8, it is safe to store -/// any `char` in a `str` or read any character from a `str` as a `char`. +/// Unicode scalar values are also the exact set of values that may be encoded in UTF-8. Because +/// `char` values are Unicode scalar values and functions may assume [incoming `str` values are +/// valid UTF-8](primitive.str.html#invariant), it is safe to store any `char` in a `str` or read +/// any character from a `str` as a `char`. /// /// The gap in valid `char` values is understood by the compiler, so in the /// below example the two ranges are understood to cover the whole range of @@ -324,11 +325,17 @@ mod prim_never {} /// }; /// ``` /// -/// All USVs are valid `char` values, but not all of them represent a real -/// character. Many USVs are not currently assigned to a character, but may be -/// in the future ("reserved"); some will never be a character -/// ("noncharacters"); and some may be given different meanings by different -/// users ("private use"). +/// All Unicode scalar values are valid `char` values, but not all of them represent a real +/// character. Many Unicode scalar values are not currently assigned to a character, but may be in +/// the future ("reserved"); some will never be a character ("noncharacters"); and some may be given +/// different meanings by different users ("private use"). +/// +/// `char` is guaranteed to have the same size and alignment as `u32` on all +/// platforms. +/// ``` +/// use std::alloc::Layout; +/// assert_eq!(Layout::new::(), Layout::new::()); +/// ``` /// /// [Unicode code point]: https://www.unicode.org/glossary/#code_point /// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value @@ -887,8 +894,6 @@ mod prim_slice {} /// type. It is usually seen in its borrowed form, `&str`. It is also the type /// of string literals, `&'static str`. /// -/// String slices are always valid UTF-8. -/// /// # Basic Usage /// /// String literals are string slices: @@ -942,6 +947,14 @@ mod prim_slice {} /// Note: This example shows the internals of `&str`. `unsafe` should not be /// used to get a string slice under normal circumstances. Use `as_str` /// instead. +/// +/// # Invariant +/// +/// Rust libraries may assume that string slices are always valid UTF-8. +/// +/// Constructing a non-UTF-8 string slice is not immediate undefined behavior, but any function +/// called on a string slice may assume that it is valid UTF-8, which means that a non-UTF-8 string +/// slice can lead to undefined behavior down the road. #[stable(feature = "rust1", since = "1.0.0")] mod prim_str {} diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 84b179df8c19..fc4943c2aa9a 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(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(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() -> *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() -> *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(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 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 50127b27f8bf..90c346e98bcc 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -835,8 +835,6 @@ impl Result { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// let x: u8 = "4" /// .parse::() /// .inspect(|x| println!("original: {x}")) @@ -844,7 +842,7 @@ impl Result { /// .expect("failed to parse number"); /// ``` #[inline] - #[unstable(feature = "result_option_inspect", issue = "91345")] + #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] pub fn inspect(self, f: F) -> Self { if let Ok(ref t) = self { f(t); @@ -858,8 +856,6 @@ impl Result { /// # Examples /// /// ``` - /// #![feature(result_option_inspect)] - /// /// use std::{fs, io}; /// /// fn read() -> io::Result { @@ -868,7 +864,7 @@ impl Result { /// } /// ``` #[inline] - #[unstable(feature = "result_option_inspect", issue = "91345")] + #[stable(feature = "result_option_inspect", since = "CURRENT_RUSTC_VERSION")] pub fn inspect_err(self, f: F) -> Self { if let Err(ref e) = self { f(e); diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 45080eda2ce2..6cf5d48a1678 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -640,6 +640,11 @@ impl [T] { /// Calling this method with an out-of-bounds index is *[undefined behavior]* /// even if the resulting reference is not used. /// + /// You can think of this like `.get(index).unwrap_unchecked()`. It's UB + /// to call `.get_unchecked(len)`, even if you immediately convert to a + /// pointer. And it's UB to call `.get_unchecked(..len + 1)`, + /// `.get_unchecked(..=len)`, or similar. + /// /// [`get`]: slice::get /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// @@ -675,6 +680,11 @@ impl [T] { /// Calling this method with an out-of-bounds index is *[undefined behavior]* /// even if the resulting reference is not used. /// + /// You can think of this like `.get_mut(index).unwrap_unchecked()`. It's + /// UB to call `.get_unchecked_mut(len)`, even if you immediately convert + /// to a pointer. And it's UB to call `.get_unchecked_mut(..len + 1)`, + /// `.get_unchecked_mut(..=len)`, or similar. + /// /// [`get_mut`]: slice::get_mut /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index db76d26257aa..993a608f42b6 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 b5ad3f280e6b..f83f60857a26 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::()` (note that on some platforms this can /// be bigger than `align_of::()`). /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. - /// * Non-atomic accesses to the value behind `ptr` must have a happens-before relationship - /// with atomic accesses via the returned value (or vice-versa). - /// * In other words, time periods where the value is accessed atomically may not overlap - /// with periods where the value is accessed non-atomically. - /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the - /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. - /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done - /// from the same thread. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, + /// without synchronization. /// /// [valid]: crate::ptr#safety + /// [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 AtomicPtr { /// * `ptr` must be aligned to `align_of::>()` (note that on some platforms this /// can be bigger than `align_of::<*mut T>()`). /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. - /// * Non-atomic accesses to the value behind `ptr` must have a happens-before relationship - /// with atomic accesses via the returned value (or vice-versa). - /// * In other words, time periods where the value is accessed atomically may not overlap - /// with periods where the value is accessed non-atomically. - /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the - /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. - /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done - /// from the same thread. - /// * This method should not be used to create overlapping or mixed-size atomic accesses, as - /// these are not supported by the memory model. + /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not + /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes, + /// without synchronization. /// /// [valid]: crate::ptr#safety + /// [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 { @@ -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 b63fd5c9095f..817e39942c05 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 b9ede65c9ff0..1ddcd5ab7955 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 033bd1ed6ed9..5268f32c0319 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -167,7 +167,7 @@ fn test_indirect_hasher() { #[test] fn test_build_hasher_object_safe() { - use std::collections::hash_map::{DefaultHasher, RandomState}; + use std::hash::{DefaultHasher, RandomState}; let _: &dyn BuildHasher = &RandomState::new(); } diff --git a/library/std/src/io/readbuf/tests.rs b/library/core/tests/io/borrowed_buf.rs similarity index 98% rename from library/std/src/io/readbuf/tests.rs rename to library/core/tests/io/borrowed_buf.rs index 89a2f6b2271b..69511e49acdb 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 000000000000..a24893a525a9 --- /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 df7b34ce73b4..c167240ba243 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::>(); diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 5c2e18745ea2..20498b16cb22 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -565,3 +565,24 @@ fn offset_of_addr() { assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr()); assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr()); } + +#[test] +fn const_maybe_uninit_zeroed() { + // Sanity check for `MaybeUninit::zeroed` in a realistic const situation (plugin array term) + #[repr(C)] + struct Foo { + a: Option<&'static str>, + b: Bar, + c: f32, + d: *const u8, + } + #[repr(C)] + struct Bar(usize); + struct FooPtr(*const Foo); + unsafe impl Sync for FooPtr {} + + static UNINIT: FooPtr = FooPtr([unsafe { MaybeUninit::zeroed().assume_init() }].as_ptr()); + const SIZE: usize = size_of::(); + + assert_eq!(unsafe { (*UNINIT.0.cast::<[[u8; SIZE]; 1]>())[0] }, [0u8; SIZE]); +} diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 2eb7608c7ae6..f666b18887cb 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 4d109285d164..39e94902cfe5 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -6,16 +6,13 @@ use self::Entry::*; use hashbrown::hash_map as base; use crate::borrow::Borrow; -use crate::cell::Cell; use crate::collections::TryReserveError; use crate::collections::TryReserveErrorKind; use crate::error::Error; use crate::fmt::{self, Debug}; -#[allow(deprecated)] -use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13}; +use crate::hash::{BuildHasher, Hash, RandomState}; use crate::iter::FusedIterator; use crate::ops::Index; -use crate::sys; /// A [hash map] implemented with quadratic probing and SIMD lookup. /// @@ -274,7 +271,7 @@ impl HashMap { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut map = HashMap::with_hasher(s); @@ -306,7 +303,7 @@ impl HashMap { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut map = HashMap::with_capacity_and_hasher(10, s); @@ -717,7 +714,7 @@ impl HashMap { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let hasher = RandomState::new(); /// let map: HashMap = HashMap::with_hasher(hasher); @@ -3072,152 +3069,6 @@ where } } -/// `RandomState` is the default state for [`HashMap`] types. -/// -/// A particular instance `RandomState` will create the same instances of -/// [`Hasher`], but the hashers created by two different `RandomState` -/// instances are unlikely to produce the same result for the same values. -/// -/// # Examples -/// -/// ``` -/// use std::collections::HashMap; -/// use std::collections::hash_map::RandomState; -/// -/// let s = RandomState::new(); -/// let mut map = HashMap::with_hasher(s); -/// map.insert(1, 2); -/// ``` -#[derive(Clone)] -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -pub struct RandomState { - k0: u64, - k1: u64, -} - -impl RandomState { - /// Constructs a new `RandomState` that is initialized with random keys. - /// - /// # Examples - /// - /// ``` - /// use std::collections::hash_map::RandomState; - /// - /// let s = RandomState::new(); - /// ``` - #[inline] - #[allow(deprecated)] - // rand - #[must_use] - #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] - pub fn new() -> RandomState { - // Historically this function did not cache keys from the OS and instead - // simply always called `rand::thread_rng().gen()` twice. In #31356 it - // was discovered, however, that because we re-seed the thread-local RNG - // from the OS periodically that this can cause excessive slowdown when - // many hash maps are created on a thread. To solve this performance - // trap we cache the first set of randomly generated keys per-thread. - // - // Later in #36481 it was discovered that exposing a deterministic - // iteration order allows a form of DOS attack. To counter that we - // increment one of the seeds on every RandomState creation, giving - // every corresponding HashMap a different iteration order. - thread_local!(static KEYS: Cell<(u64, u64)> = { - Cell::new(sys::hashmap_random_keys()) - }); - - KEYS.with(|keys| { - let (k0, k1) = keys.get(); - keys.set((k0.wrapping_add(1), k1)); - RandomState { k0, k1 } - }) - } -} - -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -impl BuildHasher for RandomState { - type Hasher = DefaultHasher; - #[inline] - #[allow(deprecated)] - fn build_hasher(&self) -> DefaultHasher { - DefaultHasher(SipHasher13::new_with_keys(self.k0, self.k1)) - } -} - -/// The default [`Hasher`] used by [`RandomState`]. -/// -/// The internal algorithm is not specified, and so it and its hashes should -/// not be relied upon over releases. -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -#[allow(deprecated)] -#[derive(Clone, Debug)] -pub struct DefaultHasher(SipHasher13); - -impl DefaultHasher { - /// Creates a new `DefaultHasher`. - /// - /// This hasher is not guaranteed to be the same as all other - /// `DefaultHasher` instances, but is the same as all other `DefaultHasher` - /// instances created through `new` or `default`. - #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] - #[inline] - #[allow(deprecated)] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] - #[must_use] - pub const fn new() -> DefaultHasher { - DefaultHasher(SipHasher13::new_with_keys(0, 0)) - } -} - -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Default for DefaultHasher { - /// Creates a new `DefaultHasher` using [`new`]. - /// See its documentation for more. - /// - /// [`new`]: DefaultHasher::new - #[inline] - fn default() -> DefaultHasher { - DefaultHasher::new() - } -} - -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Hasher for DefaultHasher { - // The underlying `SipHasher13` doesn't override the other - // `write_*` methods, so it's ok not to forward them here. - - #[inline] - fn write(&mut self, msg: &[u8]) { - self.0.write(msg) - } - - #[inline] - fn write_str(&mut self, s: &str) { - self.0.write_str(s); - } - - #[inline] - fn finish(&self) -> u64 { - self.0.finish() - } -} - -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -impl Default for RandomState { - /// Constructs a new `RandomState`. - #[inline] - fn default() -> RandomState { - RandomState::new() - } -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for RandomState { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RandomState").finish_non_exhaustive() - } -} - #[inline] fn map_entry<'a, K: 'a, V: 'a>(raw: base::RustcEntry<'a, K, V>) -> Entry<'a, K, V> { match raw { diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs index 91a3776e7be8..8585376abc18 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 6a87f6e5f2dc..8bc596082906 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -6,11 +6,11 @@ use hashbrown::hash_set as base; use crate::borrow::Borrow; use crate::collections::TryReserveError; use crate::fmt; -use crate::hash::{BuildHasher, Hash}; +use crate::hash::{BuildHasher, Hash, RandomState}; use crate::iter::{Chain, FusedIterator}; use crate::ops::{BitAnd, BitOr, BitXor, Sub}; -use super::map::{map_try_reserve_error, RandomState}; +use super::map::map_try_reserve_error; /// A [hash set] implemented as a `HashMap` where the value is `()`. /// @@ -361,7 +361,7 @@ impl HashSet { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut set = HashSet::with_hasher(s); @@ -393,7 +393,7 @@ impl HashSet { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut set = HashSet::with_capacity_and_hasher(10, s); @@ -411,7 +411,7 @@ impl HashSet { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let hasher = RandomState::new(); /// let set: HashSet = HashSet::with_hasher(hasher); diff --git a/library/std/src/collections/hash/set/tests.rs b/library/std/src/collections/hash/set/tests.rs index e0cd80b44f8e..208f61e755c5 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 42f738acb9f7..1389d24a8c51 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 000000000000..bd9bbf298752 --- /dev/null +++ b/library/std/src/hash/mod.rs @@ -0,0 +1,91 @@ +//! Generic hashing support. +//! +//! This module provides a generic way to compute the [hash] of a value. +//! Hashes are most commonly used with [`HashMap`] and [`HashSet`]. +//! +//! [hash]: https://en.wikipedia.org/wiki/Hash_function +//! [`HashMap`]: ../../std/collections/struct.HashMap.html +//! [`HashSet`]: ../../std/collections/struct.HashSet.html +//! +//! The simplest way to make a type hashable is to use `#[derive(Hash)]`: +//! +//! # Examples +//! +//! ```rust +//! use std::hash::{DefaultHasher, Hash, Hasher}; +//! +//! #[derive(Hash)] +//! struct Person { +//! id: u32, +//! name: String, +//! phone: u64, +//! } +//! +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; +//! +//! assert!(calculate_hash(&person1) != calculate_hash(&person2)); +//! +//! fn calculate_hash(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); +//! t.hash(&mut s); +//! s.finish() +//! } +//! ``` +//! +//! If you need more control over how a value is hashed, you need to implement +//! the [`Hash`] trait: +//! +//! ```rust +//! use std::hash::{DefaultHasher, Hash, Hasher}; +//! +//! struct Person { +//! id: u32, +//! # #[allow(dead_code)] +//! name: String, +//! phone: u64, +//! } +//! +//! impl Hash for Person { +//! fn hash(&self, state: &mut H) { +//! self.id.hash(state); +//! self.phone.hash(state); +//! } +//! } +//! +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; +//! +//! assert_eq!(calculate_hash(&person1), calculate_hash(&person2)); +//! +//! fn calculate_hash(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); +//! t.hash(&mut s); +//! s.finish() +//! } +//! ``` +#![stable(feature = "rust1", since = "1.0.0")] + +pub(crate) mod random; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::hash::*; + +#[stable(feature = "std_hash_exports", since = "CURRENT_RUSTC_VERSION")] +pub use self::random::{DefaultHasher, RandomState}; diff --git a/library/std/src/hash/random.rs b/library/std/src/hash/random.rs new file mode 100644 index 000000000000..a1ccbb25369b --- /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 57d226a3771e..4d51a719f6ca 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 BufferedWriterSpec for Vec { fn copy_from(&mut self, reader: &mut R) -> Result { let mut bytes = 0; - // avoid allocating before we have determined that there's anything to read - if self.capacity() == 0 { - bytes = stack_buffer_copy(&mut reader.take(DEFAULT_BUF_SIZE as u64), self)?; - if bytes == 0 { - return Ok(0); + // 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(); + + // EOF + if bytes_read == 0 { + return 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), + } } - - // SAFETY: BorrowedBuf guarantees all of its filled bytes are init - // and the number of read bytes can't exceed the spare capacity since - // that's what the buffer is borrowing from. - unsafe { self.set_len(self.len() + read) }; - bytes += read as u64; } - - Ok(bytes) } } diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index f438325560f5..256b043a6097 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -528,3 +528,17 @@ impl Write for VecDeque { Ok(()) } } + +#[unstable(feature = "read_buf", issue = "78485")] +impl<'a> io::Write for core::io::BorrowedCursor<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { + let amt = cmp::min(buf.len(), self.capacity()); + self.append(&buf[..amt]); + Ok(amt) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index aa9a2482d2d9..7d70a0bac24f 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 f57c8d4e7e28..f716c0fe9228 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::>(); diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index f12ffbf2e016..dbc0f7d9df35 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -1,8 +1,7 @@ use super::*; -use crate::collections::hash_map::DefaultHasher; use crate::collections::{BTreeSet, HashSet}; -use crate::hash::Hasher; +use crate::hash::{DefaultHasher, Hasher}; use crate::rc::Rc; use crate::sync::Arc; use core::hint::black_box; @@ -1461,8 +1460,7 @@ fn test_eq_receivers() { #[test] pub fn test_compare() { - use crate::collections::hash_map::DefaultHasher; - use crate::hash::{Hash, Hasher}; + use crate::hash::{DefaultHasher, Hash, Hasher}; fn hash(t: T) -> u64 { let mut s = DefaultHasher::new(); diff --git a/library/std/tests/common/mod.rs b/library/std/tests/common/mod.rs index 358c2c3f9b2f..1aad6549e76c 100644 --- a/library/std/tests/common/mod.rs +++ b/library/std/tests/common/mod.rs @@ -1,17 +1,17 @@ #![allow(unused)] +use rand::RngCore; use std::env; use std::fs; use std::path::{Path, PathBuf}; use std::thread; -use rand::RngCore; /// Copied from `std::test_helpers::test_rng`, since these tests rely on the /// seed not being the same for every RNG invocation too. #[track_caller] pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { use core::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = std::collections::hash_map::RandomState::new().build_hasher(); + let mut hasher = std::hash::RandomState::new().build_hasher(); core::panic::Location::caller().hash(&mut hasher); let hc64 = hasher.finish(); let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); diff --git a/library/test/src/helpers/shuffle.rs b/library/test/src/helpers/shuffle.rs index ca503106c556..2ac3bfbd4d6f 100644 --- a/library/test/src/helpers/shuffle.rs +++ b/library/test/src/helpers/shuffle.rs @@ -1,7 +1,6 @@ use crate::cli::TestOpts; use crate::types::{TestDescAndFn, TestId, TestName}; -use std::collections::hash_map::DefaultHasher; -use std::hash::Hasher; +use std::hash::{DefaultHasher, Hasher}; use std::time::{SystemTime, UNIX_EPOCH}; pub fn get_shuffle_seed(opts: &TestOpts) -> Option { diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index bddf75dffbb6..f92ffa94e99f 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -264,8 +264,8 @@ pub fn run_tests( where F: FnMut(TestEvent) -> io::Result<()>, { - use std::collections::{self, HashMap}; - use std::hash::BuildHasherDefault; + use std::collections::HashMap; + use std::hash::{BuildHasherDefault, DefaultHasher}; use std::sync::mpsc::RecvTimeoutError; struct RunningTest { @@ -286,8 +286,7 @@ where } // Use a deterministic hasher - type TestMap = - HashMap>; + type TestMap = HashMap>; struct TimeoutEntry { id: TestId, diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index eab2717c4523..9aa552ed81ab 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 5c3c02fb6ada..000000000000 --- 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 e86408a9ed2b..335bded71c16 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 346bfb30fecf..57113b0ec62c 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -180,16 +180,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" version = "0.8.2" @@ -323,15 +313,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hex" version = "0.4.3" @@ -443,16 +424,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" version = "0.32.0" @@ -514,25 +485,22 @@ dependencies = [ [[package]] name = "rayon" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 1a1125a107fe..5a84e37f8cfa 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 e6caabec4f64..6da410ed2f27 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 626ca6cf2e7a..544a42d9ada1 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 113df88d7c34..7c33ce958c92 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 ffc38057900a..9998fe2f5db8 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 d87fb6a9cef0..0a6072ae1a5d 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 { } let latest_config_id = CONFIG_CHANGE_HISTORY.last().unwrap(); - let suggestion = if let Some(id) = config.change_id { - if &id != latest_config_id { - msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); - let change_links: Vec = find_recent_config_change_ids(id) - .iter() - .map(|id| format!("https://github.com/rust-lang/rust/pull/{id}")) - .collect(); - if !change_links.is_empty() { - msg.push_str("To see more detail about these changes, visit the following PRs:\n"); - for link in change_links { - msg.push_str(&format!(" - {link}\n")); - } - } - msg.push_str("WARNING: there have been changes to x.py since you last updated.\n"); - format!("update `config.toml` to use `change-id = {latest_config_id}` instead") - } else { + if let Some(id) = config.change_id { + if &id == latest_config_id { return None; } + + let change_links: Vec = find_recent_config_change_ids(id) + .iter() + .map(|id| format!("https://github.com/rust-lang/rust/pull/{id}")) + .collect(); + if !change_links.is_empty() { + msg.push_str("WARNING: there have been changes to x.py since you last updated.\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"); + + 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 3041fd37ac80..070a2da6afb8 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::>(); 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 121925b56a05..d36c41906b0c 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 679770ce0ec7..cbb6b5f46488 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 1eed534150bb..7021a9543582 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 b578c5ec2950..c485481b9a1e 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1298,6 +1298,10 @@ impl Step for CodegenBackend { } fn run(self, builder: &Builder<'_>) -> Option { + if builder.config.dry_run() { + return None; + } + // This prevents rustc_codegen_cranelift from being built for "dist" // or "install" on the stable/beta channels. It is not yet stable and // should not be included. @@ -1305,6 +1309,10 @@ impl Step for CodegenBackend { return None; } + if !builder.config.rust_codegen_backends.contains(&self.backend) { + return None; + } + if self.backend == "cranelift" { if !target_supports_cranelift_backend(self.compiler.host) { builder.info("target not supported by rustc_codegen_cranelift. skipping"); @@ -1343,12 +1351,15 @@ impl Step for CodegenBackend { let backends_dst = PathBuf::from("lib").join(&backends_rel); let backend_name = format!("rustc_codegen_{}", backend); + let mut found_backend = false; for backend in fs::read_dir(&backends_src).unwrap() { let file_name = backend.unwrap().file_name(); if file_name.to_str().unwrap().contains(&backend_name) { tarball.add_file(backends_src.join(file_name), &backends_dst, 0o644); + found_backend = true; } } + assert!(found_backend); Some(tarball.generate()) } @@ -1619,14 +1630,11 @@ impl Step for Extended { prepare("rust-analysis"); prepare("clippy"); prepare("rust-analyzer"); - for tool in &["rust-docs", "rust-demangler", "miri"] { + for tool in &["rust-docs", "rust-demangler", "miri", "rustc-codegen-cranelift"] { if built_tools.contains(tool) { prepare(tool); } } - if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("cranelift")) { - prepare("rustc-codegen-cranelift"); - } // create an 'uninstall' package builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755); pkgbuild("uninstall"); @@ -2208,23 +2216,19 @@ impl Step for RustDev { builder.ensure(crate::core::build_steps::llvm::Lld { target }); let src_bindir = builder.llvm_out(target).join("bin"); - // If updating this list, you likely want to change + // If updating this, you likely want to change // src/bootstrap/download-ci-llvm-stamp as well, otherwise local users // will not pick up the extra file until LLVM gets bumped. - for bin in &[ - "llvm-config", - "llvm-ar", - "llvm-objdump", - "llvm-profdata", - "llvm-bcanalyzer", - "llvm-cov", - "llvm-dwp", - "llvm-nm", - "llvm-dwarfdump", - "llvm-dis", - "llvm-tblgen", - ] { - tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755); + // We should include all the build artifacts obtained from a source build, + // so that you can use the downloadable LLVM as if you’ve just run a full source build. + if src_bindir.exists() { + for entry in walkdir::WalkDir::new(&src_bindir) { + let entry = t!(entry); + if entry.file_type().is_file() && !entry.path_is_symlink() { + let name = entry.file_name().to_str().unwrap(); + tarball.add_file(src_bindir.join(name), "bin", 0o755); + } + } } // We don't build LLD on some platforms, so only add it if it exists diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 628a4ece8e90..e3fd942fc380 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 0e260e69c85a..86f1d925f73d 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -89,7 +89,7 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result>, Str return Ok(None); } - get_git_modified_files(Some(&build.config.src), &vec!["rs"]) + get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &vec!["rs"]) } #[derive(serde_derive::Deserialize)] diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 9d03350c7232..6b4a8f597eab 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 5b4543077216..a1f6fac8a518 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 435ebb6df90d..486a1e20f183 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 { 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> { "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 82fb10cebe07..93da27560c65 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 e2b515a30867..254fbc72a8c7 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 d5f759ea159a..e8327b751d38 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 ` 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 f892577ccbf7..a451f92b6bcb 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 44cdbe38de36..cd276674dee6 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 f56e46010f37..0a9175aa3ea5 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, + 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 { + // Handle running from a directory other than the top level + let top_level = output(self.git().args(&["rev-parse", "--show-toplevel"])); + let top_level = top_level.trim_end(); + + // Look for a version to compare to based on the current commit. + // Only commits merged by bors will have CI artifacts. + let merge_base = output( + self.git() + .arg("rev-list") + .arg(format!("--author={}", self.stage0_metadata.config.git_merge_commit_email)) + .args(&["-n1", "--first-parent", "HEAD"]), + ); + let commit = merge_base.trim_end(); + if commit.is_empty() { + println!("error: could not find commit hash for downloading components from CI"); + println!("help: maybe your repository history is too shallow?"); + println!("help: consider disabling `{option_name}`"); + println!("help: or fetch enough history to include one upstream commit"); + crate::exit!(1); + } + + // Warn if there were changes to the compiler or standard library since the ancestor commit. + let mut git = self.git(); + git.args(&["diff-index", "--quiet", &commit, "--"]); + + for path in modified_paths { + git.arg(format!("{top_level}/{path}")); + } + + let has_changes = !t!(git.status()).success(); + if has_changes { + if if_unchanged { + if self.verbose > 0 { + println!( + "warning: saw changes to one of {modified_paths:?} since {commit}; \ + ignoring `{option_name}`" + ); + } + return None; + } + println!( + "warning: `{option_name}` is enabled, but there are changes to one of {modified_paths:?}" + ); + } + + Some(commit.to_string()) + } } fn set(field: &mut T, val: Option) { diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 64af114f998e..2a301007ab47 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 5541a2f3e35e..3327aed9600b 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 d7f49a6d11b9..33b8f1a7ce72 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::>(); - // 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 { - 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 b9177c490ac2..c90fd2805e28 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 82a5607d9037..5bc81f2d983e 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 65794f05d2d9..174f374224c0 100644 --- a/src/bootstrap/src/utils/metrics.rs +++ b/src/bootstrap/src/utils/metrics.rs @@ -180,7 +180,7 @@ impl BuildMetrics { t!(serde_json::from_slice::(&contents)).invocations } else { println!( - "warning: overriding existing build/metrics.json, as it's not \ + "WARNING: overriding existing build/metrics.json, as it's not \ compatible with build metrics format version {CURRENT_FORMAT_VERSION}." ); Vec::new() diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index f97aa9585135..bff47f65c51f 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 56ee348a337e..1d9568702cc3 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 3b3ec5da74bc..e939a5d7eac4 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 a2891ef95634..cedbc0390f8f 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 f78d446c8b7c..437b51641fc9 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 b415eb5961bb..da29ffb8e5f9 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 31ef55216b91..ce0dd6018af8 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 000000000000..fab126453fdc --- /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 index 16fd3c06d9e5..cd8193e972f6 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 16fd3c06d9e558dae2d52000818274ae70c9e90a +Subproject commit cd8193e972f61b92117095fc73b67af767b4d6bc diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 6709beeb7d0f..311b84962016 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 6709beeb7d0fbc5ffc91ac4893a24434123b9bfa +Subproject commit 311b84962016b28c75525c86e7b3f49fd9101a39 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index b0ee9ec8fa59..77dbe5782b24 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit b0ee9ec8fa59a6c7620165e061f4747202377a62 +Subproject commit 77dbe5782b2488af3bb489ad702eaff438f465bf diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 8b4d673d831c..1b27b77b3e6b 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 172048704f48..d4e2fc52e973 100644 --- a/src/doc/rustc/src/exploit-mitigations.md +++ b/src/doc/rustc/src/exploit-mitigations.md @@ -1,12 +1,12 @@ # Exploit Mitigations -This chapter documents the exploit mitigations supported by the Rust -compiler, and is by no means an extensive survey of the Rust programming -language’s security features. +This chapter documents the exploit mitigations supported by the Rust compiler, +and is by no means an extensive survey of the Rust programming language’s +security features. This chapter is for software engineers working with the Rust programming -language, and assumes prior knowledge of the Rust programming language and -its toolchain. +language, and assumes prior knowledge of the Rust programming language and its +toolchain. ## Introduction @@ -14,8 +14,8 @@ its toolchain. The Rust programming language provides memory[1] and thread[2] safety guarantees via its ownership[3], references and borrowing[4], and slice types[5] features. However, Unsafe Rust[6] introduces unsafe blocks, unsafe -functions and methods, unsafe traits, and new types that are not subject to -the borrowing rules. +functions and methods, unsafe traits, and new types that are not subject to the +borrowing rules. Parts of the Rust standard library are implemented as safe abstractions over unsafe code (and historically have been vulnerable to memory corruption[7]). @@ -23,33 +23,32 @@ Furthermore, the Rust code and documentation encourage creating safe abstractions over unsafe code. This can cause a false sense of security if unsafe code is not properly reviewed and tested. -Unsafe Rust introduces features that do not provide the same memory and -thread safety guarantees. This causes programs or libraries to be -susceptible to memory corruption (CWE-119)[8] and concurrency issues -(CWE-557)[9]. Modern C and C++ compilers provide exploit mitigations to -increase the difficulty to exploit vulnerabilities resulting from these -issues. Therefore, the Rust compiler must also support these exploit -mitigations in order to mitigate vulnerabilities resulting from the use of -Unsafe Rust. This chapter documents these exploit mitigations and how they -apply to Rust. +Unsafe Rust introduces features that do not provide the same memory and thread +safety guarantees. This causes programs or libraries to be susceptible to +memory corruption (CWE-119)[8] and concurrency issues (CWE-557)[9]. Modern C +and C++ compilers provide exploit mitigations to increase the difficulty to +exploit vulnerabilities resulting from these issues. Therefore, the Rust +compiler must also support these exploit mitigations in order to mitigate +vulnerabilities resulting from the use of Unsafe Rust. This chapter documents +these exploit mitigations and how they apply to Rust. -This chapter does not discuss the effectiveness of these exploit mitigations -as they vary greatly depending on several factors besides their design and -implementation, but rather describe what they do, so their effectiveness can -be understood within a given context. +This chapter does not discuss the effectiveness of these exploit mitigations as +they vary greatly depending on several factors besides their design and +implementation, but rather describe what they do, so their effectiveness can be +understood within a given context. ## Exploit mitigations -This section documents the exploit mitigations applicable to the Rust -compiler when building programs for the Linux operating system on the AMD64 -architecture and equivalent.1 +This section documents the exploit mitigations applicable to the Rust compiler +when building programs for the Linux operating system on the AMD64 architecture +and equivalent.1 All examples in this section were built using +nightly builds of the Rust compiler on Debian testing. -The Rust Programming Language currently has no specification. The Rust -compiler (i.e., rustc) is the language reference implementation. All -references to “the Rust compiler” in this chapter refer to the language -reference implementation. +The Rust Programming Language currently has no specification. The Rust compiler +(i.e., rustc) is the language reference implementation. All references to “the +Rust compiler” in this chapter refer to the language reference implementation. Table I \ Summary of exploit mitigations supported by the Rust compiler when building @@ -83,8 +82,8 @@ instructing the dynamic linker to load it similarly to a shared object at a random load address, thus also benefiting from address-space layout randomization (ASLR). This is also referred to as “full ASLR”. -The Rust compiler supports position-independent executable, and enables it -by default since version 0.12.0 (2014-10-09)[10]–[13]. +The Rust compiler supports position-independent executable, and enables it by +default since version 0.12.0 (2014-10-09)[10]–[13]. ```text $ readelf -h target/release/hello-rust | grep Type: @@ -93,8 +92,7 @@ $ readelf -h target/release/hello-rust | grep Type: Fig. 1. Checking if an executable is a position-independent executable. An executable with an object type of `ET_DYN` (i.e., shared object) and not -`ET_EXEC` (i.e., executable) is a position-independent executable (see Fig. -1). +`ET_EXEC` (i.e., executable) is a position-independent executable (see Fig. 1). ### Integer overflow checks @@ -104,8 +102,11 @@ behavior (which may cause vulnerabilities) by checking for results of signed and unsigned integer computations that cannot be represented in their type, resulting in an overflow or wraparound. -The Rust compiler supports integer overflow checks, and enables it when -debug assertions are enabled since version 1.1.0 (2015-06-25)[14]–[20]. +The Rust compiler supports integer overflow checks, and enables it when debug +assertions are enabled since version 1.0.0 (2015-05-15)[14]–[17], but support +for it was not completed until version 1.1.0 (2015-06-25)[16]. An option to +control integer overflow checks was later stabilized in version 1.17.0 +(2017-04-27)[18]–[20]. ```compile_fail fn main() { @@ -136,21 +137,21 @@ u: 0 Fig. 4. Build and execution of hello-rust-integer with debug assertions disabled. -Integer overflow checks are enabled when debug assertions are enabled (see -Fig. 3), and disabled when debug assertions are disabled (see Fig. 4). To -enable integer overflow checks independently, use the option to control -integer overflow checks, scoped attributes, or explicit checking methods -such as `checked_add`2. -It is recommended that explicit wrapping methods such as `wrapping_add` be -used when wrapping semantics are intended, and that explicit checking and -wrapping methods always be used when using Unsafe Rust. +It is recommended that explicit wrapping methods such as `wrapping_add` be used +when wrapping semantics are intended, and that explicit checking and wrapping +methods always be used when using Unsafe Rust. -2\. See [the `u32` docs](../std/primitive.u32.html) -for more information on the checked, overflowing, saturating, and wrapping -methods (using u32 as an example). +2\. See [the `u32` docs](../std/primitive.u32.html) for more +information on the checked, overflowing, saturating, and wrapping methods +(using u32 as an example). ### Non-executable memory regions @@ -158,17 +159,16 @@ class="reversefootnote" role="doc-backlink">↩ Non-executable memory regions increase the difficulty of exploitation by limiting the memory regions that can be used to execute arbitrary code. Most modern processors provide support for the operating system to mark memory -regions as non executable, but it was previously emulated by software, such -as in grsecurity/PaX's -[PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt) and -[SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors that -did not provide support for it. This is also known as “No Execute (NX) Bit”, -“Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others. +regions as non executable, but it was previously emulated by software, such as +in grsecurity/PaX’s [PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt) +and [SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors +that did not provide support for it. This is also known as “No Execute (NX) +Bit”, “Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others. The Rust compiler supports non-executable memory regions, and enables it by -default since its initial release, version 0.1 (2012-01-20)[21], [22], but -has regressed since then[23]–[25], and enforced by default since version -1.8.0 (2016-04-14)[25]. +default since its initial release, version 0.1 (2012-01-20)[21], [22], but has +regressed since then[23]–[25], and enforced by default since version 1.8.0 +(2016-04-14)[25]. ```text $ readelf -l target/release/hello-rust | grep -A 1 GNU_STACK @@ -178,9 +178,9 @@ $ readelf -l target/release/hello-rust | grep -A 1 GNU_STACK Fig. 5. Checking if non-executable memory regions are enabled for a given binary. -The presence of an element of type `PT_GNU_STACK` in the program header -table with the `PF_X` (i.e., executable) flag unset indicates non-executable -memory regions3 are enabled for a given binary (see Fig. 5). Conversely, the presence of an element of type `PT_GNU_STACK` in the program header table with the `PF_X` flag set or the absence of an element of type @@ -196,38 +196,40 @@ class="reversefootnote" role="doc-backlink">↩ Stack clashing protection protects the stack from overlapping with another memory region—allowing arbitrary data in both to be overwritten using each -other—by reading from the stack pages as the stack grows to cause a page -fault when attempting to read from the guard page/region. This is also -referred to as “stack probes” or “stack probing”. +other—by reading from the stack pages as the stack grows to cause a page fault +when attempting to read from the guard page/region. This is also referred to as +“stack probes” or “stack probing”. The Rust compiler supports stack clashing protection via stack probing, and enables it by default since version 1.20.0 (2017-08-31)[26]–[29]. -![Screenshot of IDA Pro listing cross references to __rust_probestack in hello-rust.](images/image1.png "Cross references to __rust_probestack in hello-rust.") -Fig. 6. IDA Pro listing cross references to `__rust_probestack` in -hello-rust. - ```rust -fn hello() { - println!("Hello, world!"); -} - fn main() { - let _: [u64; 1024] = [0; 1024]; - hello(); + let v: [u8; 16384] = [1; 16384]; + let first = &v[0]; + println!("The first element is: {first}"); } ``` -Fig 7. Modified hello-rust. +Fig. 6. hello-rust-stack-probe-1 program. -![Screenshot of IDA Pro listing cross references to __rust_probestack in modified hello-rust.](images/image2.png "Cross references to __rust_probestack in modified hello-rust.") -Fig. 8. IDA Pro listing cross references to `__rust_probestack` in modified -hello-rust. +![Screenshot of IDA Pro listing the "unrolled loop" stack probe variant in modified hello-rust.](images/image1.png "The \"unrolled loop\" stack probe variant in modified hello-rust.") +Fig. 7. The "unrolled loop" stack probe variant in modified hello-rust. -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. +```rust +fn main() { + let v: [u8; 65536] = [1; 65536]; + let first = &v[0]; + println!("The first element is: {first}"); +} +``` +Fig. 8. hello-rust-stack-probe-2 program. + +![Screenshot of IDA Pro listing the "standard loop" stack probe variant in modified hello-rust.](images/image2.png "The \"standard loop\" stack probe variant in modified hello-rust.") +Fig. 9. The "standard loop" stack probe variant in modified hello-rust. + +To check if stack clashing protection is enabled for a given binary, look for +any of the two stack probe variants in the prologue of functions whose stack +size is larger than a page size (see Figs. 6–9). ### Read-only relocations and immediate binding @@ -246,21 +248,20 @@ $ readelf -l target/release/hello-rust | grep GNU_RELRO ``` Fig. 9. Checking if read-only relocations is enabled for a given binary. -The presence of an element of type `PT_GNU_RELRO` in the program header -table indicates read-only relocations are enabled for a given binary (see -Fig. 9). Conversely, the absence of an element of type `PT_GNU_RELRO` in the -program header table indicates read-only relocations are not enabled for a -given binary. +The presence of an element of type `PT_GNU_RELRO` in the program header table +indicates read-only relocations are enabled for a given binary (see Fig. 9). +Conversely, the absence of an element of type `PT_GNU_RELRO` in the program +header table indicates read-only relocations are not enabled for a given +binary. **Immediate binding** protects additional segments containing relocations -(i.e., `.got.plt`) from being overwritten by instructing the dynamic linker -to perform all relocations before transferring control to the program during -startup, so all segments containing relocations can be marked read only -(when combined with read-only relocations). This is also referred to as -“full RELRO”. +(i.e., `.got.plt`) from being overwritten by instructing the dynamic linker to +perform all relocations before transferring control to the program during +startup, so all segments containing relocations can be marked read only (when +combined with read-only relocations). This is also referred to as “full RELRO”. -The Rust compiler supports immediate binding, and enables it by default -since version 1.21.0 (2017-10-12)[30], [31]. +The Rust compiler supports immediate binding, and enables it by default since +version 1.21.0 (2017-10-12)[30], [31]. ```text $ readelf -d target/release/hello-rust | grep BIND_NOW @@ -270,16 +271,15 @@ Fig. 10. Checking if immediate binding is enabled for a given binary. The presence of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag4 in the dynamic section indicates immediate -binding is enabled for a given binary (see Fig. 10). Conversely, the absence -of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag in the -dynamic section indicates immediate binding is not enabled for a given -binary. +class="footnote">4 in the dynamic section indicates immediate binding +is enabled for a given binary (see Fig. 10). Conversely, the absence of an +element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag in the dynamic +section indicates immediate binding is not enabled for a given binary. The presence of both an element of type `PT_GNU_RELRO` in the program header -table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` -flag in the dynamic section indicates full RELRO is enabled for a given -binary (see Fig. 9 and Fig. 10). +table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag +in the dynamic section indicates full RELRO is enabled for a given binary (see +Figs. 9–10). 4\. And the `DF_1_NOW` flag for some link editors. @@ -287,26 +287,24 @@ href="#fnref:4" class="reversefootnote" role="doc-backlink">↩ ### Heap corruption protection -Heap corruption protection protects memory allocated dynamically by -performing several checks, such as checks for corrupted links between list -elements, invalid pointers, invalid sizes, double/multiple “frees” of the -same memory allocated, and many corner cases of these. These checks are -implementation specific, and vary per allocator. +Heap corruption protection protects memory allocated dynamically by performing +several checks, such as checks for corrupted links between list elements, +invalid pointers, invalid sizes, double/multiple “frees” of the same memory +allocated, and many corner cases of these. These checks are implementation +specific, and vary per allocator. [ARM Memory Tagging Extension (MTE)](https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/enhancing-memory-safety), -when available, will provide hardware assistance for a probabilistic -mitigation to detect memory safety violations by tagging memory allocations, -and automatically checking that the correct tag is used on every memory -access. +when available, will provide hardware assistance for a probabilistic mitigation +to detect memory safety violations by tagging memory allocations, and +automatically checking that the correct tag is used on every memory access. Rust’s default allocator has historically been -[jemalloc](http://jemalloc.net/), and it has long been the cause of issues -and the subject of much discussion[32]–[38]. Consequently, it has been -removed as the default allocator in favor of the operating system’s standard -C library default allocator5 since version 1.32.0 -(2019-01-17)[39]. +[jemalloc](http://jemalloc.net/), and it has long been the cause of issues and +the subject of much discussion[32]–[38]. Consequently, it has been removed as +the default allocator in favor of the operating system’s standard C library +default allocator5 since version 1.32.0 (2019-01-17)[39]. ```rust,no_run fn main() { @@ -330,8 +328,7 @@ $ cargo run free(): invalid next size (normal) Aborted ``` -Fig. 12. Build and execution of hello-rust-heap with debug assertions -enabled. +Fig. 12. Build and execution of hello-rust-heap with debug assertions enabled. ```text $ cargo run --release @@ -341,47 +338,41 @@ $ cargo run --release free(): invalid next size (normal) Aborted ``` -Fig. 13. Build and execution of hello-rust-heap with debug assertions -disabled. +Fig. 13. Build and execution of hello-rust-heap with debug assertions disabled. -Heap corruption checks are being performed when using the default allocator -(i.e., the GNU Allocator) as seen in Fig. 12 and Fig. 13. +Heap corruption checks are performed when using the default allocator (i.e., +the GNU Allocator) (see Figs. 12–13). 5\. Linux's standard C library default allocator is the GNU -Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram -Gloger, which in turn is derived from dlmalloc (Doug Lea malloc) by Doug -Lea. +Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram Gloger, +which in turn is derived from dlmalloc (Doug Lea malloc) by Doug Lea. ### Stack smashing protection -Stack smashing protection protects programs from stack-based buffer -overflows by inserting a random guard value between local variables and the -saved return instruction pointer, and checking if this value has changed -when returning from a function. This is also known as “Stack Protector” or -“Stack Smashing Protector (SSP)”. +Stack smashing protection protects programs from stack-based buffer overflows +by inserting a random guard value between local variables and the saved return +instruction pointer, and checking if this value has changed when returning from +a function. This is also known as “Stack Protector” or “Stack Smashing +Protector (SSP)”. -The Rust compiler supports stack smashing protection on nightly builds[42]. +The Rust compiler supports stack smashing protection on nightly builds[40]. ![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.") -Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in -hello-rust. +Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in hello-rust. -To check if stack smashing protection is enabled for a given binary, search -for cross references to `__stack_chk_fail`. The presence of these -cross-references in Rust-compiled code (e.g., `hello_rust::main`) indicates -that the stack smashing protection is enabled (see Fig. 14). +To check if stack smashing protection is enabled for a given binary, search for +cross references to `__stack_chk_fail` (see Fig. 14). ### Forward-edge control flow protection -Forward-edge control flow protection protects programs from having its -control flow changed/hijacked by performing checks to ensure that -destinations of indirect branches are one of their valid destinations in the -control flow graph. The comprehensiveness of these checks vary per -implementation. This is also known as “forward-edge control flow integrity -(CFI)”. +Forward-edge control flow protection protects programs from having its control +flow changed/hijacked by performing checks to ensure that destinations of +indirect branches are one of their valid destinations in the control flow +graph. The comprehensiveness of these checks vary per implementation. This is +also known as “forward-edge control flow integrity (CFI)”. Newer processors provide hardware assistance for forward-edge control flow protection, such as ARM Branch Target Identification (BTI), ARM Pointer @@ -394,22 +385,19 @@ commercially available [grsecurity/PaX Reuse Attack Protector (RAP)](https://grsecurity.net/rap_faq). The Rust compiler supports forward-edge control flow protection on nightly -builds[40]-[41] 6. ```text -$ readelf -s -W target/debug/rust-cfi | grep "\.cfi" - 12: 0000000000005170 46 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_one.cfi - 15: 00000000000051a0 16 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_two.cfi - 17: 0000000000005270 396 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi4main.cfi -... +$ readelf -s -W target/release/hello-rust | grep "\.cfi" + 5: 0000000000006480 657 FUNC LOCAL DEFAULT 15 _ZN10hello_rust4main17h4e359f1dcd627c83E.cfi ``` -Fig. 15. Checking if LLVM CFI is enabled for a given binary[41]. +Fig. 15. Checking if LLVM CFI is enabled for a given binary. The presence of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and -references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge control -flow protection) is enabled for a given binary. Conversely, the absence of -symbols suffixed with ".cfi" or the `__cfi_init` symbol (and references to +references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge +control flow protection) is enabled for a given binary. Conversely, the absence +of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and references to `__cfi_check`) indicates that LLVM CFI is not enabled for a given binary (see Fig. 15). @@ -421,48 +409,47 @@ class="reversefootnote" role="doc-backlink">↩ ### Backward-edge control flow protection **Shadow stack** protects saved return instruction pointers from being -overwritten by storing a copy of them on a separate (shadow) stack, and -using these copies as authoritative values when returning from functions. -This is also known as “ShadowCallStack” and “Return Flow Guard”, and is -considered an implementation of backward-edge control flow protection (or -“backward-edge CFI”). +overwritten by storing a copy of them on a separate (shadow) stack, and using +these copies as authoritative values when returning from functions. This is +also known as “ShadowCallStack” and “Return Flow Guard”, and is considered an +implementation of backward-edge control flow protection (or “backward-edge +CFI”). **Safe stack** protects not only the saved return instruction pointers, but -also register spills and some local variables from being overwritten by -storing unsafe variables, such as large arrays, on a separate (unsafe) -stack, and using these unsafe variables on the separate stack instead. This -is also known as “SafeStack”, and is also considered an implementation of -backward-edge control flow protection. +also register spills and some local variables from being overwritten by storing +unsafe variables, such as large arrays, on a separate (unsafe) stack, and using +these unsafe variables on the separate stack instead. This is also known as +“SafeStack”, and is also considered an implementation of backward-edge control +flow protection. -Both shadow and safe stack are intended to be a more comprehensive -alternatives to stack smashing protection as they protect the saved return -instruction pointers (and other data in the case of safe stack) from -arbitrary writes and non-linear out-of-bounds writes. +Both shadow and safe stack are intended to be a more comprehensive alternatives +to stack smashing protection as they protect the saved return instruction +pointers (and other data in the case of safe stack) from arbitrary writes and +non-linear out-of-bounds writes. Newer processors provide hardware assistance for backward-edge control flow -protection, such as ARM Pointer Authentication, and Intel Shadow Stack as -part of Intel CET. +protection, such as ARM Pointer Authentication, and Intel Shadow Stack as part +of Intel CET. -The Rust compiler supports shadow stack for aarch64 only -7 -on nightly Rust compilers [43]-[44]. Safe stack is available on nightly -Rust compilers [45]-[46]. +The Rust compiler supports shadow stack for the AArch64 architecture7on +nightly builds[43]-[44], and also supports safe stack on nightly +builds[45]-[46]. ```text $ readelf -s target/release/hello-rust | grep __safestack_init - 1177: 00000000000057b0 444 FUNC GLOBAL DEFAULT 9 __safestack_init + 678: 0000000000008c80 426 FUNC GLOBAL DEFAULT 15 __safestack_init ``` Fig. 16. Checking if LLVM SafeStack is enabled for a given binary. -The presence of the `__safestack_init` symbol indicates that LLVM SafeStack -is enabled for a given binary (see Fig. 16). Conversely, the absence of the -`__safestack_init` symbol indicates that LLVM SafeStack is not enabled for a -given binary. +The presence of the `__safestack_init` symbol indicates that LLVM SafeStack is +enabled for a given binary. Conversely, the absence of the `__safestack_init` +symbol indicates that LLVM SafeStack is not enabled for a given binary (see +Fig. 16). -7\. The shadow stack implementation for the AMD64 -architecture and equivalent in LLVM was removed due to performance and -security issues. +7\. The shadow stack implementation for the AMD64 architecture +and equivalent in LLVM was removed due to performance and security issues. ## Appendix @@ -470,29 +457,28 @@ role="doc-backlink">↩ As of the latest version of the [Linux Standard Base (LSB) Core Specification](https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/progheader.html), the `PT_GNU_STACK` program header indicates whether the stack should be -executable, and the absence of this header indicates that the stack should -be executable. However, the Linux kernel currently sets the -`READ_IMPLIES_EXEC` personality upon loading any executable with the -`PT_GNU_STACK` program header and the `PF_X `flag set or with the absence of -this header, resulting in not only the stack, but also all readable virtual -memory mappings being executable. +executable, and the absence of this header indicates that the stack should be +executable. However, the Linux kernel currently sets the `READ_IMPLIES_EXEC` +personality upon loading any executable with the `PT_GNU_STACK` program header +and the `PF_X` flag set or with the absence of this header, resulting in not +only the stack, but also all readable virtual memory mappings being executable. An attempt to fix this [was made in 2012](https://lore.kernel.org/lkml/f298f914-2239-44e4-8aa1-a51282e7fac0@zmail15.collab.prod.int.phx2.redhat.com/), and another [was made in 2020](https://lore.kernel.org/kernel-hardening/20200327064820.12602-1-keescook@chromium.org/). The former never landed, and the latter partially fixed it, but introduced -other issues—the absence of the `PT_GNU_STACK` program header still causes -not only the stack, but also all readable virtual memory mappings to be -executable in some architectures, such as IA-32 and equivalent (or causes -the stack to be non-executable in some architectures, such as AMD64 and -equivalent, contradicting the LSB). +other issues—the absence of the `PT_GNU_STACK` program header still causes not +only the stack, but also all readable virtual memory mappings to be executable +in some architectures, such as IA-32 and equivalent (or causes the stack to be +non-executable in some architectures, such as AMD64 and equivalent, +contradicting the LSB). -The `READ_IMPLIES_EXEC` personality needs to be completely separated from -the `PT_GNU_STACK` program header by having a separate option for it (or -setarch -X could just be used whenever `READ_IMPLIES_EXEC` is needed), and -the absence of the `PT_GNU_STACK` program header needs to have more secure -defaults (unrelated to `READ_IMPLIES_EXEC`). +The `READ_IMPLIES_EXEC` personality needs to be completely separated from the +`PT_GNU_STACK` program header by having a separate option for it (or setarch -X +could just be used whenever `READ_IMPLIES_EXEC` is needed), and the absence of +the `PT_GNU_STACK` program header needs to have more secure defaults (unrelated +to `READ_IMPLIES_EXEC`). ## References @@ -576,19 +562,19 @@ defaults (unrelated to `READ_IMPLIES_EXEC`). 25. A. Clark. “Explicitly disable stack execution on linux and bsd #30859.” GitHub. . -26. “Replace stack overflow checking with stack probes #16012.” GitHub. +26. Zoxc. “Replace stack overflow checking with stack probes #16012.” GitHub. . -27. B. Striegel. “Extend stack probe support to non-tier-1 platforms, and - clarify policy for mitigating LLVM-dependent unsafety #43241.” GitHub. - . - -28. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub. +27. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub. . -29. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub. +28. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub. . +29. S. Guelton, S. Ledru, J. Stone. “Bringing Stack Clash Protection to Clang / + X86 — the Open Source Way.” The LLVM Project Blog. + . + 30. B. Anderson. “Consider applying -Wl,-z,relro or -Wl,-z,relro,-z,now by default #29877.” GitHub. . @@ -621,16 +607,16 @@ defaults (unrelated to `READ_IMPLIES_EXEC`). 39. A. Crichton. “Remove the alloc\_jemalloc crate #55238.” GitHub. . -40. R. de C Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support - for Rust #89653.” GitHub. . - -41. “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.” +40. bbjornse. “Add codegen option for using LLVM stack smash protection #84197.” GitHub. -43. ivanloz. “Add support for LLVM ShadowCallStack. #98208.” GitHub. +41. R. de C. Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support + for Rust #89653.” GitHub. . + +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). + +43. I. Lozano. “Add support for LLVM ShadowCallStack #98208.” GitHub. . 44. “ShadowCallStack.” The Rust Unstable Book. diff --git a/src/doc/rustc/src/images/image1.png b/src/doc/rustc/src/images/image1.png index ee2d3fd4f43c..0da45e56620d 100644 Binary files a/src/doc/rustc/src/images/image1.png and b/src/doc/rustc/src/images/image1.png differ diff --git a/src/doc/rustc/src/images/image2.png b/src/doc/rustc/src/images/image2.png index 03061e1f0b12..a9cf23f87377 100644 Binary files a/src/doc/rustc/src/images/image2.png and b/src/doc/rustc/src/images/image2.png differ diff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png index ef02c605ead8..844a2fe67472 100644 Binary files a/src/doc/rustc/src/images/image3.png and b/src/doc/rustc/src/images/image3.png differ diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 6a979869a59a..907e9c59f316 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 000000000000..c3ce71a18356 --- /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 f7cce35b1232..34ab3cdaf25e 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 bdf6a0f6b239..eb946e82f399 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -743,7 +743,7 @@ impl<'a, 'tcx> TypeFolder> for RegionReplacer<'a, 'tcx> { match *r { // These are the regions that can be seen in the AST. ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned().unwrap_or(r), - ty::ReEarlyBound(_) | ty::ReStatic | ty::ReLateBound(..) | ty::ReError(_) => r, + ty::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 013814b1f7dc..974ba1e3bd93 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 e6e2d60f2e5b..d33e41dc2b39 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 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 `` 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 a718cb37d89f..88ee4e3a2abd 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 }, Type { did: DefId, bounds: ThinVec, default: Option>, synthetic: bool }, + // Option> makes this type smaller than `Option` would. Const { ty: Box, default: Option>, is_host_effect: bool }, } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index dea7bfaf7e22..9ff00c1946fc 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 3e58dd96ed92..d2c7c578c083 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!( "

List of all crates

    {}
", - krates - .iter() - .map(|s| { - format!( - "
  • {s}
  • ", - trailing_slash = ensure_trailing_slash(s), - ) - }) - .collect::() + krates.iter().format_with("", |k, f| { + f(&format_args!( + "
  • {k}
  • ", + trailing_slash = ensure_trailing_slash(k), + )) + }) ); let v = layout::render(&shared.layout, &page, "", content, &shared.style_files); shared.fs.write(dst, v)?; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 7c052606abac..615fb08c76f3 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 = `${longty}`; diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index ebf817673bfe..3f6147bb916f 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -10,7 +10,6 @@ {# #} {# #} {# #} - {# #} {# #} {# #} diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index b8b7785a2a19..c75fc34a9dfe 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -54,7 +54,7 @@ Note: Encountered an error during type layout; {#+ #} the type failed to be normalized. {# #}

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

    {# #} Note: Encountered an error during type layout; {#+ #} the type's layout depended on the type's layout itself. {# #} diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 0c15bf5f764f..472781e7d229 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 index fef3d7b14ede..773829517804 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit fef3d7b14ede45d051dc688aae0bb8c8b02a0566 +Subproject commit 7738295178045041669876bf32b0543ec8319a5c diff --git a/src/stage0.json b/src/stage0.json index 32dc8a2f83c6..2b39e1b11589 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 2c795ebb2148..aed6796fa13c 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::>().join("."); self.write_channel_files(&major_minor, &manifest); + } else if channel == "beta" { + // channel-rust-1.XX.YY-beta.Z.toml + let rust_version = self + .versions + .version(&PkgType::Rust) + .expect("missing Rust tarball") + .version + .expect("missing Rust version") + .split(' ') + .next() + .unwrap() + .to_string(); + self.write_channel_files(&rust_version, &manifest); + + // channel-rust-1.XX.YY-beta.toml + let major_minor_patch_beta = + rust_version.split('.').take(3).collect::>().join("."); + self.write_channel_files(&major_minor_patch_beta, &manifest); + + // channel-rust-1.XX-beta.toml + let major_minor_beta = + format!("{}-beta", rust_version.split('.').take(2).collect::>().join(".")); + self.write_channel_files(&major_minor_beta, &manifest); } if let Some(path) = std::env::var_os("BUILD_MANIFEST_SHIPPED_FILES_PATH") { diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index f20b7a2b4d72..b91dc38e9248 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -1,6 +1,11 @@ use std::process::Stdio; use std::{path::Path, process::Command}; +pub struct GitConfig<'a> { + pub git_repository: &'a str, + pub nightly_branch: &'a str, +} + /// Runs a command and returns the output fn output_result(cmd: &mut Command) -> Result { let output = match cmd.stderr(Stdio::inherit()).output() { @@ -27,7 +32,10 @@ fn output_result(cmd: &mut Command) -> Result { /// upstream https://github.com/rust-lang/rust (fetch) /// upstream https://github.com/rust-lang/rust (push) /// ``` -pub fn get_rust_lang_rust_remote(git_dir: Option<&Path>) -> Result { +pub fn get_rust_lang_rust_remote( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result { let mut git = Command::new("git"); if let Some(git_dir) = git_dir { git.current_dir(git_dir); @@ -37,8 +45,8 @@ pub fn get_rust_lang_rust_remote(git_dir: Option<&Path>) -> Result) -> Result { /// This could be because the user is updating their forked master branch using the GitHub UI /// and therefore doesn't need an upstream master branch checked out. /// We will then fall back to origin/master in the hope that at least this exists. -pub fn updated_master_branch(git_dir: Option<&Path>) -> Result { - let upstream_remote = get_rust_lang_rust_remote(git_dir)?; - for upstream_master in [format!("{upstream_remote}/master"), format!("origin/master")] { +pub fn updated_master_branch( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result { + let upstream_remote = get_rust_lang_rust_remote(config, git_dir)?; + let branch = config.nightly_branch; + for upstream_master in [format!("{upstream_remote}/{branch}"), format!("origin/{branch}")] { if rev_exists(&upstream_master, git_dir)? { return Ok(upstream_master); } @@ -87,8 +99,11 @@ pub fn updated_master_branch(git_dir: Option<&Path>) -> Result { Err(format!("Cannot find any suitable upstream master branch")) } -pub fn get_git_merge_base(git_dir: Option<&Path>) -> Result { - let updated_master = updated_master_branch(git_dir)?; +pub fn get_git_merge_base( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result { + let updated_master = updated_master_branch(config, git_dir)?; let mut git = Command::new("git"); if let Some(git_dir) = git_dir { git.current_dir(git_dir); @@ -100,10 +115,11 @@ pub fn get_git_merge_base(git_dir: Option<&Path>) -> Result { /// The `extensions` parameter can be used to filter the files by their extension. /// If `extensions` is empty, all files will be returned. pub fn get_git_modified_files( + config: &GitConfig<'_>, git_dir: Option<&Path>, extensions: &Vec<&str>, ) -> Result>, String> { - let merge_base = get_git_merge_base(git_dir)?; + let merge_base = get_git_merge_base(config, git_dir)?; let mut git = Command::new("git"); if let Some(git_dir) = git_dir { @@ -122,8 +138,11 @@ pub fn get_git_modified_files( } /// Returns the files that haven't been added to git yet. -pub fn get_git_untracked_files(git_dir: Option<&Path>) -> Result>, String> { - let Ok(_updated_master) = updated_master_branch(git_dir) else { +pub fn get_git_untracked_files( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result>, String> { + let Ok(_updated_master) = updated_master_branch(config, git_dir) else { return Ok(None); }; let mut git = Command::new("git"); diff --git a/src/tools/cargo b/src/tools/cargo index b4d18d4bd3db..6790a5127895 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit b4d18d4bd3db6d872892f6c87c51a02999b80802 +Subproject commit 6790a5127895debec95c24aefaeb18e059270df3 diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index fad8fbf04497..02c53fafd696 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 4d7a055dae17..d6fa742b7968 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 83863b92caff..c6ac96a4539c 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 ce93aea21360..152248afc903 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 7eff93881b26..2ff979f2dcb3 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( impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow> TypeVisitor> for V { type BreakTy = B; fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow { - if let RegionKind::ReLateBound(idx, bound) = r.kind() + if let RegionKind::ReBound(idx, bound) = r.kind() && idx.as_u32() == self.index { (self.f)(bound) @@ -1160,7 +1160,7 @@ pub fn make_normalized_projection<'tcx>( ) -> Option> { fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] - if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_late_bound_regions()) { + if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_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> { fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] - if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_late_bound_regions()) { + if let Some((i, arg)) = ty.args.iter().enumerate().find(|(_, arg)| arg.has_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 eb3e5189c823..140300a16730 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 e1b95aa57760..5c277f925a8f 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 0e1bf0c6c2dc..1e9684555f1f 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, 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 948439d6e79d..d6516cff63fb 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -911,11 +911,11 @@ pub fn make_test_description( let mut should_fail = false; let extra_directives: &[&str] = match config.mode { - // The run-coverage tests are treated as having these extra directives, + // The coverage-run tests are treated as having these extra directives, // without needing to specify them manually in every test file. // (Some of the comments below have been copied over from // `tests/run-make/coverage-reports/Makefile`, which no longer exists.) - Mode::RunCoverage => { + Mode::CoverageRun => { &[ "needs-profiler-support", // FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 2fd80b52ceee..85e745bed112 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -126,6 +126,8 @@ impl ConfigBuilder { self.host.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), "--target", self.target.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), + "--git-repository=", + "--nightly-branch=", ]; let mut args: Vec = args.iter().map(ToString::to_string).collect(); diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 619ff9b32211..bb09c03ef5b7 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) -> 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) -> 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, 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 e74d66a85992..8854908c430a 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/rust-version b/src/tools/miri/rust-version index 2beb3bfef9e5..0d677d36e362 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -3aaa0f57b7b877ef58532a8de075d1e5a79142bf +6d069a0ac7a423db87d86320edd39974f9f0c492 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 d47af50d407e..e79bd70e915e 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 381442e69b13..ccf9732ed079 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 3d8ba68547bd..e7baf6e23db7 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 ea773048dd4e..e4c00fdd8456 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 cba23c21d12b..f8140d0236af 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 8c6a7df7a6dd..517abd733a9c 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 f8532186be20..c37e788e6b44 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 7b1846a32dbc..7557d3710d18 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 0a31adabf73d..dd951066c324 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 3d560af3d5eb..23b1e38b99f7 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 875cc5edad98..cf13be6da012 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 deafbf020772..e16c4c0ebb67 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 c1bbc748e1a0..56706cdb63ba 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 0666db34fec4..5d76d9eab67f 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 e1b40a6bc183..e8165a73ff4f 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 79e29b79d6a2..923c59e74299 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 ee80186d4b50..9357b3725050 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 234c28040086..b40d99f7bc95 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 d410a875b1be..89ee689fabe1 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 310a8a5be7ad..9a5015005b3d 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 fb7b4b07f984..1f2a7796d114 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 bbeccd1621df..741e559953fc 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 bd6554bf8899..fcb188c0dfab 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -32,12 +32,6 @@ version = "1.0.71" 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" @@ -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", @@ -617,27 +608,6 @@ dependencies = [ "typed-arena", ] -[[package]] -name = "hkalbasi-rustc-ap-rustc_abi" -version = "0.0.20221221" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adabaadad9aa7576f97af02241cdf5554d62fb3d51a84cb05d77ba28edd3013f" -dependencies = [ - "bitflags 1.3.2", - "hkalbasi-rustc-ap-rustc_index", - "tracing", -] - -[[package]] -name = "hkalbasi-rustc-ap-rustc_index" -version = "0.0.20221221" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4d3c48474e09afb0f5efbd6f758e05411699301a113c47d454d28ec7059d00e" -dependencies = [ - "arrayvec", - "smallvec", -] - [[package]] name = "home" version = "0.5.5" @@ -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,10 +1453,31 @@ dependencies = [ ] [[package]] -name = "ra-ap-rustc_index" -version = "0.10.0" +name = "ra-ap-rustc_abi" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b5fa61d34da18e148dc3a81f654488ea07f40938d8aefb17f8b64bb78c6120" +checksum = "7082716cb2bbcd8b5f062fe950cbbc87f3aba022d6da4168db35af6732a7f15d" +dependencies = [ + "bitflags 1.3.2", + "ra-ap-rustc_index 0.18.0", + "tracing", +] + +[[package]] +name = "ra-ap-rustc_index" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +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", @@ -1494,9 +1485,19 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.10.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e2f6b48422e4eed5218277ab7cc9733e60dd8f3167f4f36a49a0cafe4dc195" +checksum = "30ffd24f9ba4f1d25ff27ca1469b8d22a3bdfb12cf644fc8bfcb63121fa5da6b" +dependencies = [ + "unicode-properties", + "unicode-xid", +] + +[[package]] +name = "ra-ap-rustc_lexer" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +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", @@ -1626,6 +1629,16 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-dependencies" +version = "0.0.0" +dependencies = [ + "ra-ap-rustc_abi", + "ra-ap-rustc_index 0.18.0", + "ra-ap-rustc_lexer 0.18.0", + "ra-ap-rustc_parse_format", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -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 cab88fc18cec..c382a5a37d23 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 b75c7079be78..65db5c0fc7d3 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; } +#[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 af204e44e6ee..c5c4afa30f79 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; - /// The crate graph. + /// The proc macros. #[salsa::input] fn proc_macros(&self) -> Arc; } diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs index 2de719af92ce..0749d91eb32a 100644 --- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs +++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs @@ -50,6 +50,7 @@ pub enum FlycheckConfig { extra_args: Vec, extra_env: FxHashMap, ansi_color_output: bool, + target_dir: Option, }, CustomCommand { command: String, @@ -308,6 +309,7 @@ impl FlycheckActor { features, extra_env, ansi_color_output, + target_dir, } => { let mut cmd = Command::new(toolchain::cargo()); cmd.arg(command); @@ -340,6 +342,9 @@ impl FlycheckActor { cmd.arg(features.join(" ")); } } + if let Some(target_dir) = target_dir { + cmd.arg("--target-dir").arg(target_dir); + } cmd.envs(extra_env); (cmd, extra_args) } diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml index 8cf61ee04d4e..99b8e9bf0e14 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 c6454eb9ea02..fa3025e0303d 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 c0baf6011f79..1942c60c075d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -57,7 +57,7 @@ pub struct Body { pub type ExprPtr = AstPtr; pub type ExprSource = InFile; -pub type PatPtr = Either, AstPtr>; +pub type PatPtr = AstPtr>; pub type PatSource = InFile; pub type LabelPtr = AstPtr; @@ -356,12 +356,12 @@ impl BodySourceMap { } pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option { - let src = node.map(|it| Either::Left(AstPtr::new(it))); + let src = node.map(|it| AstPtr::new(it).wrap_left()); self.pat_map.get(&src).cloned() } pub fn node_self_param(&self, node: InFile<&ast::SelfParam>) -> Option { - let src = node.map(|it| Either::Right(AstPtr::new(it))); + let src = node.map(|it| AstPtr::new(it).wrap_right()); self.pat_map.get(&src).cloned() } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index cc02df80a8ff..e4158d7564bd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -196,16 +196,12 @@ impl ExprCollector<'_> { if let Some(self_param) = param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false)) { - let ptr = AstPtr::new(&self_param); - let binding_id: la_arena::Idx = self.alloc_binding( - name![self], - BindingAnnotation::new( - self_param.mut_token().is_some() && self_param.amp_token().is_none(), - false, - ), - ); - let param_pat = - self.alloc_pat(Pat::Bind { id: binding_id, subpat: None }, Either::Right(ptr)); + let is_mutable = + self_param.mut_token().is_some() && self_param.amp_token().is_none(); + let ptr = AstPtr::new(&Either::Right(self_param)); + let binding_id: la_arena::Idx = + self.alloc_binding(name![self], BindingAnnotation::new(is_mutable, false)); + let param_pat = self.alloc_pat(Pat::Bind { id: binding_id, subpat: None }, ptr); self.add_definition_to_binding(binding_id, param_pat); self.body.params.push(param_pat); } @@ -1260,8 +1256,8 @@ impl ExprCollector<'_> { (Some(id), Pat::Bind { id, subpat }) }; - let ptr = AstPtr::new(&pat); - let pat = self.alloc_pat(pattern, Either::Left(ptr)); + let ptr = AstPtr::new(&Either::Left(pat)); + let pat = self.alloc_pat(pattern, ptr); if let Some(binding_id) = binding { self.add_definition_to_binding(binding_id, pat); } @@ -1395,7 +1391,7 @@ impl ExprCollector<'_> { ast::Pat::MacroPat(mac) => match mac.macro_call() { Some(call) => { let macro_ptr = AstPtr::new(&call); - let src = self.expander.to_source(Either::Left(AstPtr::new(&pat))); + let src = self.expander.to_source(AstPtr::new(&Either::Left(pat))); let pat = self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| { this.collect_pat_opt(expanded_pat, binding_list) @@ -1430,8 +1426,8 @@ impl ExprCollector<'_> { Pat::Range { start, end } } }; - let ptr = AstPtr::new(&pat); - self.alloc_pat(pattern, Either::Left(ptr)) + let ptr = AstPtr::new(&Either::Left(pat)); + self.alloc_pat(pattern, ptr) } fn collect_pat_opt(&mut self, pat: Option, binding_list: &mut BindingList) -> PatId { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs index 2a90a09f25e8..baca293e2904 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs @@ -1,7 +1,6 @@ //! Name resolution for expressions. use hir_expand::name::Name; -use la_arena::{Arena, Idx, IdxRange, RawIdx}; -use rustc_hash::FxHashMap; +use la_arena::{Arena, ArenaMap, Idx, IdxRange, RawIdx}; use triomphe::Arc; use crate::{ @@ -17,7 +16,7 @@ pub type ScopeId = Idx; pub struct ExprScopes { scopes: Arena, scope_entries: Arena, - scope_by_expr: FxHashMap, + scope_by_expr: ArenaMap, } #[derive(Debug, PartialEq, Eq)] @@ -77,10 +76,10 @@ impl ExprScopes { } pub fn scope_for(&self, expr: ExprId) -> Option { - self.scope_by_expr.get(&expr).copied() + self.scope_by_expr.get(expr).copied() } - pub fn scope_by_expr(&self) -> &FxHashMap { + pub fn scope_by_expr(&self) -> &ArenaMap { &self.scope_by_expr } } @@ -94,7 +93,7 @@ impl ExprScopes { let mut scopes = ExprScopes { scopes: Arena::default(), scope_entries: Arena::default(), - scope_by_expr: FxHashMap::default(), + scope_by_expr: ArenaMap::with_capacity(body.exprs.len()), }; let mut root = scopes.root_scope(); scopes.add_params_bindings(body, root, &body.params); @@ -476,10 +475,7 @@ fn foo() { .pat_syntax(*body.bindings[resolved.binding()].definitions.first().unwrap()) .unwrap(); - let local_name = pat_src.value.either( - |it| it.syntax_node_ptr().to_node(file.syntax()), - |it| it.syntax_node_ptr().to_node(file.syntax()), - ); + let local_name = pat_src.value.syntax_node_ptr().to_node(file.syntax()); assert_eq!(local_name.text_range(), expected_name.syntax().text_range()); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index 68defa3858fc..718f241cf780 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 224f7328f8cd..b163112db918 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 63138aa6ad78..a59bbf7e2211 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs @@ -29,8 +29,8 @@ use std::{ ops::{Index, IndexMut}, }; -use anymap::Map; use rustc_hash::FxHashMap; +use stdx::anymap::Map; pub struct Key { _phantom: PhantomData<(K, V, P)>, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index 75025a984fcd..46d24bd4a614 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 44b7f1b4f63e..c0b507d3911a 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 = IndexMap>; @@ -94,7 +95,7 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap 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 4c812b62a46a..3c4f21d5c69b 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), - Varargs, +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Param { + /// This is [`None`] for varargs + pub type_ref: Option>, + pub ast_id: ParamAstId, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ParamAstId { + Param(FileAstId), + SelfParam(FileAstId), } bitflags::bitflags! { 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 e4702c113b85..c0a880a64bb6 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 417bd37c8a9b..5036c2b88297 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 3f87fe62b83c..495e2d476970 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 { + let def_map = self.def_map(db); + let parent = def_map[self.local_id].parent?; + def_map[parent].children.iter().find_map(|(name, module_id)| { + if *module_id == self.local_id { + Some(name.clone()) + } else { + None + } + }) + } + pub fn containing_module(self, db: &dyn db::DefDatabase) -> Option { self.def_map(db).containing_module(self.local_id) } @@ -498,10 +512,7 @@ impl_from!(Macro2Id, MacroRulesId, ProcMacroId for MacroId); impl MacroId { pub fn is_attribute(self, db: &dyn db::DefDatabase) -> bool { - match self { - MacroId::ProcMacroId(it) => it.lookup(db).kind == ProcMacroKind::Attr, - _ => false, - } + matches!(self, MacroId::ProcMacroId(it) if it.lookup(db).kind == ProcMacroKind::Attr) } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs b/src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs index 1906ed15baec..40726505491b 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 5292a5fa1b16..204227e33873 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 { + 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 b95ae05ccd45..c30807ad8849 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 7ad3659a4f6d..b395e7f4a813 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 36d69edf9d5d..b432588b2308 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::() { 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()); + 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 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); + // 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 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); } } } 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 2c1368962092..cbe1af157037 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs @@ -11,50 +11,7 @@ pub(crate) fn to_camel_case(ident: &str) -> Option { return None; } - // Taken from rustc. - let ret = ident - .trim_matches('_') - .split('_') - .filter(|component| !component.is_empty()) - .map(|component| { - let mut camel_cased_component = String::with_capacity(component.len()); - - let mut new_word = true; - let mut prev_is_lower_case = true; - - for c in component.chars() { - // Preserve the case if an uppercase letter follows a lowercase letter, so that - // `camelCase` is converted to `CamelCase`. - if prev_is_lower_case && c.is_uppercase() { - new_word = true; - } - - if new_word { - camel_cased_component.extend(c.to_uppercase()); - } else { - camel_cased_component.extend(c.to_lowercase()); - } - - prev_is_lower_case = c.is_lowercase(); - new_word = false; - } - - camel_cased_component - }) - .fold((String::new(), None), |(acc, prev): (_, Option), next| { - // separate two components with an underscore if their boundary cannot - // be distinguished using an uppercase/lowercase case distinction - let join = prev - .and_then(|prev| { - let f = next.chars().next()?; - let l = prev.chars().last()?; - Some(!char_has_case(l) && !char_has_case(f)) - }) - .unwrap_or(false); - (acc + if join { "_" } else { "" } + &next, Some(next)) - }) - .0; - Some(ret) + Some(stdx::to_camel_case(ident)) } /// Converts an identifier to a lower_snake_case form. @@ -97,7 +54,9 @@ fn is_camel_case(name: &str) -> bool { && !name.chars().any(|snd| { let ret = match fst { None => false, - Some(fst) => char_has_case(fst) && snd == '_' || char_has_case(snd) && fst == '_', + Some(fst) => { + stdx::char_has_case(fst) && snd == '_' || stdx::char_has_case(snd) && fst == '_' + } }; fst = Some(snd); @@ -135,11 +94,6 @@ fn is_snake_case bool>(ident: &str, wrong_case: F) -> bool { }) } -// Taken from rustc. -fn char_has_case(c: char) -> bool { - c.is_lowercase() || c.is_uppercase() -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs index f8cdeaa5e354..2e04bbfee83b 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 78d3c667a1f8..3d5ed1f93c0f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -420,7 +420,19 @@ pub struct InferenceResult { standard_types: InternedStandardTypes, /// Stores the types which were implicitly dereferenced in pattern binding modes. pub pat_adjustments: FxHashMap>, - pub binding_modes: ArenaMap, + /// Stores the binding mode (`ref` in `let ref x = 2`) of bindings. + /// + /// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an + /// or pattern can have multiple binding modes. For example: + /// ``` + /// fn foo(mut slice: &[u32]) -> usize { + /// slice = match slice { + /// [0, rest @ ..] | rest => rest, + /// }; + /// } + /// ``` + /// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`. + pub binding_modes: ArenaMap, pub expr_adjustments: FxHashMap>, pub(crate) closure_info: FxHashMap, FnTrait)>, // FIXME: remove this field 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 13d6b5643ac4..0805e20447a7 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 4e28ec06023e..7ff12e5b7f85 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 1a6106c0244c..603e58f9d462 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; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct RustcFieldIdx(pub LocalFieldId); + +impl RustcFieldIdx { + pub fn new(idx: usize) -> Self { + RustcFieldIdx(Idx::from_raw(RawIdx::from(idx as u32))) + } +} + +impl rustc_dependencies::index::Idx for RustcFieldIdx { + fn new(idx: usize) -> Self { + RustcFieldIdx(Idx::from_raw(RawIdx::from(idx as u32))) + } + + fn index(self) -> usize { + u32::from(self.0.into_raw()) as usize + } +} + +pub type Layout = LayoutS; pub type TagEncoding = hir_def::layout::TagEncoding; -pub type Variants = hir_def::layout::Variants; +pub type Variants = hir_def::layout::Variants; #[derive(Debug, PartialEq, Eq, Clone)] pub enum LayoutError { @@ -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::, _>>()?; let fields = fields.iter().map(|it| &**it).collect::>(); - let fields = fields.iter().collect::>(); + let fields = fields.iter().collect::>(); cx.univariant(dl, &fields, &ReprOptions::default(), kind).ok_or(LayoutError::Unknown)? } TyKind::Array(element, count) => { @@ -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::, _>>()?; let fields = fields.iter().map(|it| &**it).collect::>(); - let fields = fields.iter().collect::>(); + let fields = fields.iter().collect::>(); cx.univariant(dl, &fields, &ReprOptions::default(), StructKind::AlwaysSized) .ok_or(LayoutError::Unknown)? } @@ -398,9 +422,9 @@ pub fn layout_of_ty_recover( } fn layout_of_unit(cx: &LayoutCx<'_>, dl: &TargetDataLayout) -> Result { - cx.univariant::( + cx.univariant::( dl, - &[], + IndexSlice::empty(), &ReprOptions::default(), StructKind::AlwaysSized, ) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs index 85ef649b8959..5e713c17cf81 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs @@ -8,6 +8,7 @@ use hir_def::{ AdtId, EnumVariantId, LocalEnumVariantId, VariantId, }; use la_arena::RawIdx; +use rustc_dependencies::index::IndexVec; use smallvec::SmallVec; use triomphe::Arc; @@ -20,8 +21,8 @@ use crate::{ use super::LayoutCx; -pub(crate) fn struct_variant_idx() -> RustcEnumVariantIdx { - RustcEnumVariantIdx(LocalEnumVariantId::from_raw(RawIdx::from(0))) +pub(crate) const fn struct_variant_idx() -> RustcEnumVariantIdx { + RustcEnumVariantIdx(LocalEnumVariantId::from_raw(RawIdx::from_u32(0))) } pub fn layout_of_adt_query( @@ -74,7 +75,7 @@ pub fn layout_of_adt_query( .iter() .map(|it| it.iter().map(|it| &**it).collect::>()) .collect::>(); - let variants = variants.iter().map(|it| it.iter().collect()).collect(); + let variants = variants.iter().map(|it| it.iter().collect()).collect::>(); let result = if matches!(def, AdtId::UnionId(..)) { cx.layout_of_union(&repr, &variants).ok_or(LayoutError::Unknown)? } else { @@ -105,7 +106,7 @@ pub fn layout_of_adt_query( && variants .iter() .next() - .and_then(|it| it.last().map(|it| !it.is_unsized())) + .and_then(|it| it.iter().last().map(|it| !it.is_unsized())) .unwrap_or(true), ) .ok_or(LayoutError::SizeOverflow)? @@ -119,7 +120,15 @@ fn layout_scalar_valid_range(db: &dyn HirDatabase, def: AdtId) -> (Bound, let attr = attrs.by_key(name).tt_values(); for tree in attr { if let Some(it) = tree.token_trees.first() { - if let Ok(it) = it.to_string().parse() { + let text = it.to_string().replace('_', ""); + let (text, base) = match text.as_bytes() { + [b'0', b'x', ..] => (&text[2..], 16), + [b'0', b'o', ..] => (&text[2..], 8), + [b'0', b'b', ..] => (&text[2..], 2), + _ => (&*text, 10), + }; + + if let Ok(it) = u128::from_str_radix(text, base) { return Bound::Included(it); } } 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 bbe855a14de7..939025461f36 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 405bb001b5d1..c14339f6afe0 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 e953058ccca4..747ca54858c8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -243,16 +243,16 @@ impl Default for ProjectionStore { } impl ProjectionStore { - fn shrink_to_fit(&mut self) { + pub fn shrink_to_fit(&mut self) { self.id_to_proj.shrink_to_fit(); self.proj_to_id.shrink_to_fit(); } - fn intern_if_exist(&self, projection: &[PlaceElem]) -> Option { + pub fn intern_if_exist(&self, projection: &[PlaceElem]) -> Option { self.proj_to_id.get(projection).copied() } - fn intern(&mut self, projection: Box<[PlaceElem]>) -> ProjectionId { + pub fn intern(&mut self, projection: Box<[PlaceElem]>) -> ProjectionId { let new_id = ProjectionId(self.proj_to_id.len() as u32); match self.proj_to_id.entry(projection) { Entry::Occupied(id) => *id.get(), @@ -267,20 +267,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, // 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 41fb129652a1..74c5efd6c3f4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs @@ -24,6 +24,7 @@ use super::{ pub enum MutabilityReason { Mut { spans: Vec }, Not, + Unused, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -144,7 +145,8 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec } } }, - StatementKind::Deinit(_) + StatementKind::FakeRead(_) + | StatementKind::Deinit(_) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Nop => (), @@ -264,7 +266,10 @@ fn ever_initialized_map( is_ever_initialized = false; } } - StatementKind::Deinit(_) | StatementKind::Nop | StatementKind::StorageLive(_) => (), + StatementKind::Deinit(_) + | StatementKind::FakeRead(_) + | StatementKind::Nop + | StatementKind::StorageLive(_) => (), } } let Some(terminator) = &block.terminator else { @@ -331,16 +336,37 @@ fn ever_initialized_map( result } +fn push_mut_span(local: LocalId, span: MirSpan, result: &mut ArenaMap) { + match &mut result[local] { + MutabilityReason::Mut { spans } => spans.push(span), + it @ (MutabilityReason::Not | MutabilityReason::Unused) => { + *it = MutabilityReason::Mut { spans: vec![span] } + } + }; +} + +fn record_usage(local: LocalId, result: &mut ArenaMap) { + match &mut result[local] { + it @ MutabilityReason::Unused => { + *it = MutabilityReason::Not; + } + _ => (), + }; +} + +fn record_usage_for_operand(arg: &Operand, result: &mut ArenaMap) { + if let Operand::Copy(p) | Operand::Move(p) = arg { + record_usage(p.local, result); + } +} + fn mutability_of_locals( db: &dyn HirDatabase, body: &MirBody, ) -> ArenaMap { let mut result: ArenaMap = - body.locals.iter().map(|it| (it.0, MutabilityReason::Not)).collect(); - let mut push_mut_span = |local, span| match &mut result[local] { - MutabilityReason::Mut { spans } => spans.push(span), - it @ MutabilityReason::Not => *it = MutabilityReason::Mut { spans: vec![span] }, - }; + body.locals.iter().map(|it| (it.0, MutabilityReason::Unused)).collect(); + let ever_init_maps = ever_initialized_map(db, body); for (block_id, mut ever_init_map) in ever_init_maps.into_iter() { let block = &body.basic_blocks[block_id]; @@ -350,23 +376,51 @@ fn mutability_of_locals( match place_case(db, body, place) { ProjectionCase::Direct => { if ever_init_map.get(place.local).copied().unwrap_or_default() { - push_mut_span(place.local, statement.span); + push_mut_span(place.local, statement.span, &mut result); } else { ever_init_map.insert(place.local, true); } } ProjectionCase::DirectPart => { // Partial initialization is not supported, so it is definitely `mut` - push_mut_span(place.local, statement.span); + push_mut_span(place.local, statement.span, &mut result); } - ProjectionCase::Indirect => (), + ProjectionCase::Indirect => { + record_usage(place.local, &mut result); + } + } + 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 4364e0d323bb..62efb858511b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -162,7 +162,7 @@ pub struct Evaluator<'a> { not_special_fn_cache: RefCell>, mir_or_dyn_index_cache: RefCell>, /// Constantly dropping and creating `Locals` is very costly. We store - /// old locals that we normaly want to drop here, to reuse their allocations + /// old locals that we normally want to drop here, to reuse their allocations /// later. unused_locals_store: RefCell>>, cached_ptr_size: usize, @@ -375,10 +375,7 @@ impl MirEvalError { Err(_) => continue, }, MirSpan::PatId(p) => match source_map.pat_syntax(*p) { - Ok(s) => s.map(|it| match it { - Either::Left(e) => e.into(), - Either::Right(e) => e.into(), - }), + Ok(s) => s.map(|it| it.syntax_node_ptr()), Err(_) => continue, }, MirSpan::Unknown => continue, @@ -842,6 +839,7 @@ impl Evaluator<'_> { } StatementKind::Deinit(_) => not_supported!("de-init statement"), StatementKind::StorageLive(_) + | StatementKind::FakeRead(_) | StatementKind::StorageDead(_) | StatementKind::Nop => (), } @@ -2301,7 +2299,7 @@ impl Evaluator<'_> { match self.get_mir_or_dyn_index(def, generic_args.clone(), locals, span)? { MirOrDynIndex::Dyn(self_ty_idx) => { // In the layout of current possible receiver, which at the moment of writing this code is one of - // `&T`, `&mut T`, `Box`, `Rc`, `Arc`, and `Pin

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

    ` where `P` is one of possible receivers, // the vtable is exactly in the `[ptr_size..2*ptr_size]` bytes. So we can use it without branching on // the type. let first_arg = arg_bytes.clone().next().unwrap(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 803ef631f1e0..2de99e41659c 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 dd2dba717f95..9905d522146c 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 270f75ad9674..1120bb1c1123 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -284,6 +284,7 @@ impl MirLowerCtx<'_> { ); (current, current_else) = self.pattern_match_binding( id, + *slice, next_place, (*slice).into(), current, @@ -395,6 +396,7 @@ impl MirLowerCtx<'_> { if mode == MatchingMode::Bind { self.pattern_match_binding( *id, + pattern, cond_place, pattern.into(), current, @@ -431,13 +433,14 @@ impl MirLowerCtx<'_> { fn pattern_match_binding( &mut self, id: BindingId, + pat: PatId, cond_place: Place, span: MirSpan, current: BasicBlockId, current_else: Option, ) -> Result<(BasicBlockId, Option)> { let target_place = self.binding_local(id)?; - let mode = self.infer.binding_modes[id]; + let mode = self.infer.binding_modes[pat]; self.push_storage_live(id, current)?; self.push_assignment( current, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs index df16d0d82015..7d2bb95d931c 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 0108859ff32e..6e42bee97f79 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 d22d0d85c8e1..1446e83fa887 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 f860ee948452..09ab60dd549f 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 479138b67f82..67d3169243c6 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, AstPtr>>, + pub field: InFile>>, pub private: bool, } #[derive(Debug)] pub struct PrivateAssocItem { - pub expr_or_pat: - InFile, Either, AstPtr>>>, + pub expr_or_pat: InFile>>>, pub item: AssocItem, } #[derive(Debug)] pub struct MismatchedTupleStructPatArgCount { - pub expr_or_pat: InFile, AstPtr>>, + pub expr_or_pat: InFile>>, pub expected: usize, pub found: usize, } @@ -227,7 +227,7 @@ pub struct MissingUnsafe { #[derive(Debug)] pub struct MissingFields { pub file: HirFileId, - pub field_list_parent: Either, AstPtr>, + pub field_list_parent: AstPtr>, pub field_list_parent_path: Option>, pub missed_fields: Vec, } @@ -254,7 +254,7 @@ pub struct MissingMatchArms { #[derive(Debug)] pub struct TypeMismatch { - pub expr_or_pat: Either>, InFile>>, + pub expr_or_pat: InFile>>, pub expected: Type, pub actual: Type, } @@ -270,6 +270,11 @@ pub struct UnusedMut { pub local: Local, } +#[derive(Debug)] +pub struct UnusedVariable { + pub local: Local, +} + #[derive(Debug)] pub struct MovedOutOfRef { pub ty: Type, diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index b215ed38f28b..93859611668e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -18,6 +18,7 @@ //! . #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![recursion_limit = "512"] mod semantics; @@ -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 { - 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 -> 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 -> 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::() + { 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 { + pub fn field_offset(&self, field: Field) -> Option { match self.0.fields { layout::FieldsShape::Primitive => None, layout::FieldsShape::Union(_) => Some(0), layout::FieldsShape::Array { stride, count } => { - let i = u64::try_from(idx).ok()?; + let i = u64::try_from(field.index()).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(field.id))?.bytes()) + } + } + } + + pub fn tuple_field_offset(&self, field: usize) -> Option { + match self.0.fields { + layout::FieldsShape::Primitive => None, + layout::FieldsShape::Union(_) => Some(0), + layout::FieldsShape::Array { stride, count } => { + let i = u64::try_from(field).ok()?; + (i < count).then_some((stride * i).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 f29fb1edf00b..55c2f8324c6d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -236,9 +236,9 @@ impl SourceAnalyzer { _db: &dyn HirDatabase, pat: &ast::IdentPat, ) -> Option { - let binding_id = self.binding_id_of_pat(pat)?; + let id = self.pat_id(&pat.clone().into())?; let infer = self.infer.as_ref()?; - infer.binding_modes.get(binding_id).map(|bm| match bm { + infer.binding_modes.get(id).map(|bm| match bm { hir_ty::BindingMode::Move => BindingMode::Move, hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut), hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => { @@ -888,7 +888,7 @@ fn scope_for_offset( .scope_by_expr() .iter() .filter_map(|(id, scope)| { - let InFile { file_id, value } = source_map.expr_syntax(*id).ok()?; + let InFile { file_id, value } = source_map.expr_syntax(id).ok()?; if from_file == file_id { return Some((value.text_range(), scope)); } @@ -923,7 +923,7 @@ fn adjust( .scope_by_expr() .iter() .filter_map(|(id, scope)| { - let source = source_map.expr_syntax(*id).ok()?; + let source = source_map.expr_syntax(id).ok()?; // FIXME: correctly handle macro expansion if source.file_id != from_file { return None; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 3b162d7c4d82..c8b78b094169 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 66bc2f6dadc3..2d41243c20eb 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 7acf2ea0a0de..cafd57a97727 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 000000000000..082839118c58 --- /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, + initializer: Option, + definition: Definition, +} + +/// Attempts to find an appropriate node to apply the action to. +fn find_bool_node(ctx: &AssistContext<'_>) -> Option { + let name: ast::Name = ctx.find_node_at_offset()?; + + if let Some(let_stmt) = name.syntax().ancestors().find_map(ast::LetStmt::cast) { + let bind_pat = match let_stmt.pat()? { + ast::Pat::IdentPat(pat) => pat, + _ => { + cov_mark::hit!(not_applicable_in_non_ident_pat); + return None; + } + }; + let def = ctx.sema.to_def(&bind_pat)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_local); + return None; + } + + Some(BoolNodeData { + target_node: let_stmt.syntax().clone(), + name, + ty_annotation: let_stmt.ty(), + initializer: let_stmt.initializer(), + definition: Definition::Local(def), + }) + } else if let Some(const_) = name.syntax().parent().and_then(ast::Const::cast) { + let def = ctx.sema.to_def(&const_)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_const); + return None; + } + + Some(BoolNodeData { + target_node: const_.syntax().clone(), + name, + ty_annotation: const_.ty(), + initializer: const_.body(), + definition: Definition::Const(def), + }) + } else if let Some(static_) = name.syntax().parent().and_then(ast::Static::cast) { + let def = ctx.sema.to_def(&static_)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_static); + return None; + } + + Some(BoolNodeData { + target_node: static_.syntax().clone(), + name, + ty_annotation: static_.ty(), + initializer: static_.body(), + definition: Definition::Static(def), + }) + } else { + let field = name.syntax().parent().and_then(ast::RecordField::cast)?; + if field.name()? != name { + return None; + } + + let adt = field.syntax().ancestors().find_map(ast::Adt::cast)?; + let def = ctx.sema.to_def(&field)?; + if !def.ty(ctx.db()).is_bool() { + cov_mark::hit!(not_applicable_non_bool_field); + return None; + } + Some(BoolNodeData { + target_node: adt.syntax().clone(), + name, + ty_annotation: field.ty(), + initializer: None, + definition: Definition::Field(def), + }) + } +} + +fn replace_bool_expr(edit: &mut SourceChangeBuilder, expr: ast::Expr) { + let expr_range = expr.syntax().text_range(); + let enum_expr = bool_expr_to_enum_expr(expr); + edit.replace(expr_range, enum_expr.syntax().text()) +} + +/// Converts an expression of type `bool` to one of the new enum type. +fn bool_expr_to_enum_expr(expr: ast::Expr) -> ast::Expr { + let true_expr = make::expr_path(make::path_from_text("Bool::True")).clone_for_update(); + let false_expr = make::expr_path(make::path_from_text("Bool::False")).clone_for_update(); + + if let ast::Expr::Literal(literal) = &expr { + match literal.kind() { + ast::LiteralKind::Bool(true) => true_expr, + ast::LiteralKind::Bool(false) => false_expr, + _ => expr, + } + } else { + make::expr_if( + expr, + make::tail_only_block_expr(true_expr), + Some(ast::ElseBranch::Block(make::tail_only_block_expr(false_expr))), + ) + .clone_for_update() + } +} + +/// Replaces all usages of the target identifier, both when read and written to. +fn replace_usages( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + target_definition: Definition, + target_module: &hir::Module, +) { + for (file_id, references) in usages.iter() { + edit.edit_file(*file_id); + + let refs_with_imports = + augment_references_with_imports(edit, ctx, references, target_module); + + refs_with_imports.into_iter().rev().for_each( + |FileReferenceWithImport { range, old_name, new_name, import_data }| { + // replace the usages in patterns and expressions + if let Some(ident_pat) = old_name.syntax().ancestors().find_map(ast::IdentPat::cast) + { + cov_mark::hit!(replaces_record_pat_shorthand); + + let definition = ctx.sema.to_def(&ident_pat).map(Definition::Local); + if let Some(def) = definition { + replace_usages( + edit, + ctx, + &def.usages(&ctx.sema).all(), + target_definition, + target_module, + ) + } + } else if let Some(initializer) = find_assignment_usage(&new_name) { + cov_mark::hit!(replaces_assignment); + + replace_bool_expr(edit, initializer); + } else if let Some((prefix_expr, inner_expr)) = find_negated_usage(&new_name) { + cov_mark::hit!(replaces_negation); + + edit.replace( + prefix_expr.syntax().text_range(), + format!("{} == Bool::False", inner_expr), + ); + } else if let Some((record_field, initializer)) = old_name + .as_name_ref() + .and_then(ast::RecordExprField::for_field_name) + .and_then(|record_field| ctx.sema.resolve_record_field(&record_field)) + .and_then(|(got_field, _, _)| { + find_record_expr_usage(&new_name, got_field, target_definition) + }) + { + cov_mark::hit!(replaces_record_expr); + + let record_field = edit.make_mut(record_field); + let enum_expr = bool_expr_to_enum_expr(initializer); + record_field.replace_expr(enum_expr); + } else if let Some(pat) = find_record_pat_field_usage(&old_name) { + match pat { + ast::Pat::IdentPat(ident_pat) => { + cov_mark::hit!(replaces_record_pat); + + let definition = ctx.sema.to_def(&ident_pat).map(Definition::Local); + if let Some(def) = definition { + replace_usages( + edit, + ctx, + &def.usages(&ctx.sema).all(), + target_definition, + target_module, + ) + } + } + ast::Pat::LiteralPat(literal_pat) => { + cov_mark::hit!(replaces_literal_pat); + + if let Some(expr) = literal_pat.literal().and_then(|literal| { + literal.syntax().ancestors().find_map(ast::Expr::cast) + }) { + replace_bool_expr(edit, expr); + } + } + _ => (), + } + } else if let Some((ty_annotation, initializer)) = find_assoc_const_usage(&new_name) + { + edit.replace(ty_annotation.syntax().text_range(), "Bool"); + replace_bool_expr(edit, initializer); + } else if let Some(receiver) = find_method_call_expr_usage(&new_name) { + edit.replace( + receiver.syntax().text_range(), + format!("({} == Bool::True)", receiver), + ); + } else if new_name.syntax().ancestors().find_map(ast::UseTree::cast).is_none() { + // for any other usage in an expression, replace it with a check that it is the true variant + if let Some((record_field, expr)) = new_name + .as_name_ref() + .and_then(ast::RecordExprField::for_field_name) + .and_then(|record_field| { + record_field.expr().map(|expr| (record_field, expr)) + }) + { + record_field.replace_expr( + make::expr_bin_op( + expr, + ast::BinaryOp::CmpOp(ast::CmpOp::Eq { negated: false }), + make::expr_path(make::path_from_text("Bool::True")), + ) + .clone_for_update(), + ); + } else { + edit.replace(range, format!("{} == Bool::True", new_name.text())); + } + } + + // add imports across modules where needed + if let Some((import_scope, path)) = import_data { + insert_use(&import_scope, path, &ctx.config.insert_use); + } + }, + ) + } +} + +struct FileReferenceWithImport { + range: TextRange, + old_name: ast::NameLike, + new_name: ast::NameLike, + import_data: Option<(ImportScope, ast::Path)>, +} + +fn augment_references_with_imports( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + references: &[FileReference], + target_module: &hir::Module, +) -> Vec { + let mut visited_modules = FxHashSet::default(); + + references + .iter() + .filter_map(|FileReference { range, name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| (*range, name, scope.module())) + }) + .map(|(range, name, ref_module)| { + let old_name = name.clone(); + let new_name = edit.make_mut(name.clone()); + + // if the referenced module is not the same as the target one and has not been seen before, add an import + let import_data = if ref_module.nearest_non_block_module(ctx.db()) != *target_module + && !visited_modules.contains(&ref_module) + { + visited_modules.insert(ref_module); + + let import_scope = + ImportScope::find_insert_use_container(new_name.syntax(), &ctx.sema); + let path = ref_module + .find_use_path_prefixed( + ctx.sema.db, + ModuleDef::Module(*target_module), + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_no_std, + ) + .map(|mod_path| { + make::path_concat(mod_path_to_ast(&mod_path), make::path_from_text("Bool")) + }); + + import_scope.zip(path) + } else { + None + }; + + FileReferenceWithImport { range, old_name, new_name, import_data } + }) + .collect() +} + +fn find_assignment_usage(name: &ast::NameLike) -> Option { + let bin_expr = name.syntax().ancestors().find_map(ast::BinExpr::cast)?; + + if !bin_expr.lhs()?.syntax().descendants().contains(name.syntax()) { + cov_mark::hit!(dont_assign_incorrect_ref); + return None; + } + + if let Some(ast::BinaryOp::Assignment { op: None }) = bin_expr.op_kind() { + bin_expr.rhs() + } else { + None + } +} + +fn find_negated_usage(name: &ast::NameLike) -> Option<(ast::PrefixExpr, ast::Expr)> { + let prefix_expr = name.syntax().ancestors().find_map(ast::PrefixExpr::cast)?; + + if !matches!(prefix_expr.expr()?, ast::Expr::PathExpr(_) | ast::Expr::FieldExpr(_)) { + cov_mark::hit!(dont_overwrite_expression_inside_negation); + return None; + } + + if let Some(ast::UnaryOp::Not) = prefix_expr.op_kind() { + let inner_expr = prefix_expr.expr()?; + Some((prefix_expr, inner_expr)) + } else { + None + } +} + +fn find_record_expr_usage( + name: &ast::NameLike, + got_field: hir::Field, + target_definition: Definition, +) -> Option<(ast::RecordExprField, ast::Expr)> { + let name_ref = name.as_name_ref()?; + let record_field = ast::RecordExprField::for_field_name(name_ref)?; + let initializer = record_field.expr()?; + + if let Definition::Field(expected_field) = target_definition { + if got_field != expected_field { + return None; + } + } + + Some((record_field, initializer)) +} + +fn find_record_pat_field_usage(name: &ast::NameLike) -> Option { + let record_pat_field = name.syntax().parent().and_then(ast::RecordPatField::cast)?; + let pat = record_pat_field.pat()?; + + match pat { + ast::Pat::IdentPat(_) | ast::Pat::LiteralPat(_) | ast::Pat::WildcardPat(_) => Some(pat), + _ => None, + } +} + +fn find_assoc_const_usage(name: &ast::NameLike) -> Option<(ast::Type, ast::Expr)> { + let const_ = name.syntax().parent().and_then(ast::Const::cast)?; + if const_.syntax().parent().and_then(ast::AssocItemList::cast).is_none() { + return None; + } + + Some((const_.ty()?, const_.body()?)) +} + +fn find_method_call_expr_usage(name: &ast::NameLike) -> Option { + let method_call = name.syntax().ancestors().find_map(ast::MethodCallExpr::cast)?; + let receiver = method_call.receiver()?; + + if !receiver.syntax().descendants().contains(name.syntax()) { + return None; + } + + Some(receiver) +} + +/// Adds the definition of the new enum before the target node. +fn add_enum_def( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + target_node: SyntaxNode, + target_module: &hir::Module, +) { + let make_enum_pub = usages + .iter() + .flat_map(|(_, refs)| refs) + .filter_map(|FileReference { name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| scope.module()) + }) + .any(|module| module.nearest_non_block_module(ctx.db()) != *target_module); + let enum_def = make_bool_enum(make_enum_pub); + + let insert_before = node_to_insert_before(target_node); + let indent = IndentLevel::from_node(&insert_before); + enum_def.reindent_to(indent); + + ted::insert_all( + ted::Position::before(&edit.make_syntax_mut(insert_before)), + vec![ + enum_def.syntax().clone().into(), + make::tokens::whitespace(&format!("\n\n{indent}")).into(), + ], + ); +} + +/// Finds where to put the new enum definition. +/// Tries to find the ast node at the nearest module or at top-level, otherwise just +/// returns the input node. +fn node_to_insert_before(target_node: SyntaxNode) -> SyntaxNode { + target_node + .ancestors() + .take_while(|it| !matches!(it.kind(), SyntaxKind::MODULE | SyntaxKind::SOURCE_FILE)) + .filter(|it| ast::Item::can_cast(it.kind())) + .last() + .unwrap_or(target_node) +} + +fn make_bool_enum(make_pub: bool) -> ast::Enum { + let enum_def = make::enum_( + if make_pub { Some(make::visibility_pub()) } else { None }, + make::name("Bool"), + make::variant_list(vec![ + make::variant(make::name("True"), None), + make::variant(make::name("False"), None), + ]), + ) + .clone_for_update(); + + let derive_eq = make::attr_outer(make::meta_token_tree( + make::ext::ident_path("derive"), + make::token_tree( + T!['('], + vec![ + NodeOrToken::Token(make::tokens::ident("PartialEq")), + NodeOrToken::Token(make::token(T![,])), + NodeOrToken::Token(make::tokens::single_space()), + NodeOrToken::Token(make::tokens::ident("Eq")), + ], + ), + )) + .clone_for_update(); + enum_def.add_attr(derive_eq); + + enum_def +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::tests::{check_assist, check_assist_not_applicable}; + + #[test] + fn local_variable_with_usage() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + + if foo { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = Bool::True; + + if foo == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn local_variable_with_usage_negated() { + cov_mark::check!(replaces_negation); + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + + if !foo { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = Bool::True; + + if foo == Bool::False { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn local_variable_with_type_annotation() { + cov_mark::check!(replaces_ty_annotation); + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo: bool = false; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo: Bool = Bool::False; +} +"#, + ) + } + + #[test] + fn local_variable_with_non_literal_initializer() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = 1 == 2; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = if 1 == 2 { Bool::True } else { Bool::False }; +} +"#, + ) + } + + #[test] + fn local_variable_binexpr_usage() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = false; + let bar = true; + + if !foo && bar { + println!("foobar"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = Bool::False; + let bar = true; + + if foo == Bool::False && bar { + println!("foobar"); + } +} +"#, + ) + } + + #[test] + fn local_variable_unop_usage() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + + if *&foo { + println!("foobar"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = Bool::True; + + if *&foo == Bool::True { + println!("foobar"); + } +} +"#, + ) + } + + #[test] + fn local_variable_assigned_later() { + cov_mark::check!(replaces_assignment); + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo: bool; + foo = true; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo: Bool; + foo = Bool::True; +} +"#, + ) + } + + #[test] + fn local_variable_does_not_apply_recursively() { + check_assist( + bool_to_enum, + r#" +fn main() { + let $0foo = true; + let bar = !foo; + + if bar { + println!("bar"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let foo = Bool::True; + let bar = foo == Bool::False; + + if bar { + println!("bar"); + } +} +"#, + ) + } + + #[test] + fn local_variable_nested_in_negation() { + cov_mark::check!(dont_overwrite_expression_inside_negation); + check_assist( + bool_to_enum, + r#" +fn main() { + if !"foo".chars().any(|c| { + let $0foo = true; + foo + }) { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + if !"foo".chars().any(|c| { + let foo = Bool::True; + foo == Bool::True + }) { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn local_variable_non_bool() { + cov_mark::check!(not_applicable_non_bool_local); + check_assist_not_applicable( + bool_to_enum, + r#" +fn main() { + let $0foo = 1; +} +"#, + ) + } + + #[test] + fn local_variable_cursor_not_on_ident() { + check_assist_not_applicable( + bool_to_enum, + r#" +fn main() { + let foo = $0true; +} +"#, + ) + } + + #[test] + fn local_variable_non_ident_pat() { + cov_mark::check!(not_applicable_in_non_ident_pat); + check_assist_not_applicable( + bool_to_enum, + r#" +fn main() { + let ($0foo, bar) = (true, false); +} +"#, + ) + } + + #[test] + fn field_struct_basic() { + cov_mark::check!(replaces_record_expr); + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bar: bool, + baz: bool, +} + +fn main() { + let foo = Foo { bar: true, baz: false }; + + if foo.bar { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + bar: Bool, + baz: bool, +} + +fn main() { + let foo = Foo { bar: Bool::True, baz: false }; + + if foo.bar == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_enum_basic() { + cov_mark::check!(replaces_record_pat); + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + if let Foo::Bar { bar: baz } = foo { + if baz { + println!("foo"); + } + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + if let Foo::Bar { bar: baz } = foo { + if baz == Bool::True { + println!("foo"); + } + } +} +"#, + ) + } + + #[test] + fn field_enum_cross_file() { + check_assist( + bool_to_enum, + r#" +//- /foo.rs +pub enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn foo() { + let foo = Foo::Bar { bar: true }; +} + +//- /main.rs +use foo::Foo; + +mod foo; + +fn main() { + let foo = Foo::Bar { bar: false }; +} +"#, + r#" +//- /foo.rs +#[derive(PartialEq, Eq)] +pub enum Bool { True, False } + +pub enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn foo() { + let foo = Foo::Bar { bar: Bool::True }; +} + +//- /main.rs +use foo::{Foo, Bool}; + +mod foo; + +fn main() { + let foo = Foo::Bar { bar: Bool::False }; +} +"#, + ) + } + + #[test] + fn field_enum_shorthand() { + cov_mark::check!(replaces_record_pat_shorthand); + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + match foo { + Foo::Bar { bar } => { + if bar { + println!("foo"); + } + } + _ => (), + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + match foo { + Foo::Bar { bar } => { + if bar == Bool::True { + println!("foo"); + } + } + _ => (), + } +} +"#, + ) + } + + #[test] + fn field_enum_replaces_literal_patterns() { + cov_mark::check!(replaces_literal_pat); + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + if let Foo::Bar { bar: true } = foo { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + if let Foo::Bar { bar: Bool::True } = foo { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_enum_keeps_wildcard_patterns() { + check_assist( + bool_to_enum, + r#" +enum Foo { + Foo, + Bar { $0bar: bool }, +} + +fn main() { + let foo = Foo::Bar { bar: true }; + + if let Foo::Bar { bar: _ } = foo { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +enum Foo { + Foo, + Bar { bar: Bool }, +} + +fn main() { + let foo = Foo::Bar { bar: Bool::True }; + + if let Foo::Bar { bar: _ } = foo { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_union_basic() { + check_assist( + bool_to_enum, + r#" +union Foo { + $0foo: bool, + bar: usize, +} + +fn main() { + let foo = Foo { foo: true }; + + if unsafe { foo.foo } { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +union Foo { + foo: Bool, + bar: usize, +} + +fn main() { + let foo = Foo { foo: Bool::True }; + + if unsafe { foo.foo == Bool::True } { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_negated() { + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bar: bool, +} + +fn main() { + let foo = Foo { bar: false }; + + if !foo.bar { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + bar: Bool, +} + +fn main() { + let foo = Foo { bar: Bool::False }; + + if foo.bar == Bool::False { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_in_mod_properly_indented() { + check_assist( + bool_to_enum, + r#" +mod foo { + struct Bar { + $0baz: bool, + } + + impl Bar { + fn new(baz: bool) -> Self { + Self { baz } + } + } +} +"#, + r#" +mod foo { + #[derive(PartialEq, Eq)] + enum Bool { True, False } + + struct Bar { + baz: Bool, + } + + impl Bar { + fn new(baz: bool) -> Self { + Self { baz: if baz { Bool::True } else { Bool::False } } + } + } +} +"#, + ) + } + + #[test] + fn field_multiple_initializations() { + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bar: bool, + baz: bool, +} + +fn main() { + let foo1 = Foo { bar: true, baz: false }; + let foo2 = Foo { bar: false, baz: false }; + + if foo1.bar && foo2.bar { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + bar: Bool, + baz: bool, +} + +fn main() { + let foo1 = Foo { bar: Bool::True, baz: false }; + let foo2 = Foo { bar: Bool::False, baz: false }; + + if foo1.bar == Bool::True && foo2.bar == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn field_assigned_to_another() { + cov_mark::check!(dont_assign_incorrect_ref); + check_assist( + bool_to_enum, + r#" +struct Foo { + $0foo: bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: true }; + let mut bar = Bar { bar: true }; + + bar.bar = foo.foo; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + foo: Bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: Bool::True }; + let mut bar = Bar { bar: true }; + + bar.bar = foo.foo == Bool::True; +} +"#, + ) + } + + #[test] + fn field_initialized_with_other() { + check_assist( + bool_to_enum, + r#" +struct Foo { + $0foo: bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: true }; + let bar = Bar { bar: foo.foo }; +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + foo: Bool, +} + +struct Bar { + bar: bool, +} + +fn main() { + let foo = Foo { foo: Bool::True }; + let bar = Bar { bar: foo.foo == Bool::True }; +} +"#, + ) + } + + #[test] + fn field_method_chain_usage() { + check_assist( + bool_to_enum, + r#" +struct Foo { + $0bool: bool, +} + +fn main() { + let foo = Foo { bool: true }; + + foo.bool.then(|| 2); +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +struct Foo { + bool: Bool, +} + +fn main() { + let foo = Foo { bool: Bool::True }; + + (foo.bool == Bool::True).then(|| 2); +} +"#, + ) + } + + #[test] + fn field_non_bool() { + cov_mark::check!(not_applicable_non_bool_field); + check_assist_not_applicable( + bool_to_enum, + r#" +struct Foo { + $0bar: usize, +} + +fn main() { + let foo = Foo { bar: 1 }; +} +"#, + ) + } + + #[test] + fn const_basic() { + check_assist( + bool_to_enum, + r#" +const $0FOO: bool = false; + +fn main() { + if FOO { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +const FOO: Bool = Bool::False; + +fn main() { + if FOO == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn const_in_module() { + check_assist( + bool_to_enum, + r#" +fn main() { + if foo::FOO { + println!("foo"); + } +} + +mod foo { + pub const $0FOO: bool = true; +} +"#, + r#" +use foo::Bool; + +fn main() { + if foo::FOO == Bool::True { + println!("foo"); + } +} + +mod foo { + #[derive(PartialEq, Eq)] + pub enum Bool { True, False } + + pub const FOO: Bool = Bool::True; +} +"#, + ) + } + + #[test] + fn const_in_module_with_import() { + check_assist( + bool_to_enum, + r#" +fn main() { + use foo::FOO; + + if FOO { + println!("foo"); + } +} + +mod foo { + pub const $0FOO: bool = true; +} +"#, + r#" +use crate::foo::Bool; + +fn main() { + use foo::FOO; + + if FOO == Bool::True { + println!("foo"); + } +} + +mod foo { + #[derive(PartialEq, Eq)] + pub enum Bool { True, False } + + pub const FOO: Bool = Bool::True; +} +"#, + ) + } + + #[test] + fn const_cross_file() { + check_assist( + bool_to_enum, + r#" +//- /main.rs +mod foo; + +fn main() { + if foo::FOO { + println!("foo"); + } +} + +//- /foo.rs +pub const $0FOO: bool = true; +"#, + r#" +//- /main.rs +use foo::Bool; + +mod foo; + +fn main() { + if foo::FOO == Bool::True { + println!("foo"); + } +} + +//- /foo.rs +#[derive(PartialEq, Eq)] +pub enum Bool { True, False } + +pub const FOO: Bool = Bool::True; +"#, + ) + } + + #[test] + fn const_cross_file_and_module() { + check_assist( + bool_to_enum, + r#" +//- /main.rs +mod foo; + +fn main() { + use foo::bar; + + if bar::BAR { + println!("foo"); + } +} + +//- /foo.rs +pub mod bar { + pub const $0BAR: bool = false; +} +"#, + r#" +//- /main.rs +use crate::foo::bar::Bool; + +mod foo; + +fn main() { + use foo::bar; + + if bar::BAR == Bool::True { + println!("foo"); + } +} + +//- /foo.rs +pub mod bar { + #[derive(PartialEq, Eq)] + pub enum Bool { True, False } + + pub const BAR: Bool = Bool::False; +} +"#, + ) + } + + #[test] + fn const_in_impl_cross_file() { + check_assist( + bool_to_enum, + r#" +//- /main.rs +mod foo; + +struct Foo; + +impl Foo { + pub const $0BOOL: bool = true; +} + +//- /foo.rs +use crate::Foo; + +fn foo() -> bool { + Foo::BOOL +} +"#, + r#" +//- /main.rs +mod foo; + +struct Foo; + +#[derive(PartialEq, Eq)] +pub enum Bool { True, False } + +impl Foo { + pub const BOOL: Bool = Bool::True; +} + +//- /foo.rs +use crate::{Foo, Bool}; + +fn foo() -> bool { + Foo::BOOL == Bool::True +} +"#, + ) + } + + #[test] + fn const_in_trait() { + check_assist( + bool_to_enum, + r#" +trait Foo { + const $0BOOL: bool; +} + +impl Foo for usize { + const BOOL: bool = true; +} + +fn main() { + if ::BOOL { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +trait Foo { + const BOOL: Bool; +} + +impl Foo for usize { + const BOOL: Bool = Bool::True; +} + +fn main() { + if ::BOOL == Bool::True { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn const_non_bool() { + cov_mark::check!(not_applicable_non_bool_const); + check_assist_not_applicable( + bool_to_enum, + r#" +const $0FOO: &str = "foo"; + +fn main() { + println!("{FOO}"); +} +"#, + ) + } + + #[test] + fn static_basic() { + check_assist( + bool_to_enum, + r#" +static mut $0BOOL: bool = true; + +fn main() { + unsafe { BOOL = false }; + if unsafe { BOOL } { + println!("foo"); + } +} +"#, + r#" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +static mut BOOL: Bool = Bool::True; + +fn main() { + unsafe { BOOL = Bool::False }; + if unsafe { BOOL == Bool::True } { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn static_non_bool() { + cov_mark::check!(not_applicable_non_bool_static); + check_assist_not_applicable( + bool_to_enum, + r#" +static mut $0FOO: usize = 0; + +fn main() { + if unsafe { FOO } == 0 { + println!("foo"); + } +} +"#, + ) + } + + #[test] + fn not_applicable_to_other_names() { + check_assist_not_applicable(bool_to_enum, "fn $0main() {}") + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs index 1acd5ee97283..3f478ee7d39a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs @@ -25,9 +25,7 @@ pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext<'_>) let comment = ctx.find_token_at_offset::()?; // Only allow comments which are alone on their line if let Some(prev) = comment.syntax().prev_token() { - if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() { - return None; - } + Whitespace::cast(prev).filter(|w| w.text().contains('\n'))?; } match comment.kind().shape { @@ -78,7 +76,7 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { // Establish the target of our edit based on the comments we found let target = TextRange::new( comments[0].syntax().text_range().start(), - comments.last().unwrap().syntax().text_range().end(), + comments.last()?.syntax().text_range().end(), ); acc.add( @@ -91,8 +89,12 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { // contents of each line comment when they're put into the block comment. let indentation = IndentLevel::from_token(comment.syntax()); - let block_comment_body = - comments.into_iter().map(|c| line_comment_text(indentation, c)).join("\n"); + let block_comment_body = comments + .into_iter() + .map(|c| line_comment_text(indentation, c)) + .collect::>() + .into_iter() + .join("\n"); let block_prefix = CommentKind { shape: CommentShape::Block, ..comment.kind() }.prefix(); @@ -160,7 +162,8 @@ pub(crate) fn relevant_line_comments(comment: &ast::Comment) -> Vec { // // But since such comments aren't idiomatic we're okay with this. pub(crate) fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String { - let contents_without_prefix = comm.text().strip_prefix(comm.prefix()).unwrap(); + let text = comm.text(); + let contents_without_prefix = text.strip_prefix(comm.prefix()).unwrap_or(text); let contents = contents_without_prefix.strip_prefix(' ').unwrap_or(contents_without_prefix); // Don't add the indentation if the line is empty diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs index 7d0e424769ec..73ba3f5c4cdc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs @@ -51,22 +51,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<' // Check if there is an IfLet that we can handle. let (if_let_pat, cond_expr) = if is_pattern_cond(cond.clone()) { let let_ = single_let(cond)?; - match let_.pat() { - Some(ast::Pat::TupleStructPat(pat)) if pat.fields().count() == 1 => { - let path = pat.path()?; - if path.qualifier().is_some() { - return None; - } - - let bound_ident = pat.fields().next()?; - if !ast::IdentPat::can_cast(bound_ident.syntax().kind()) { - return None; - } - - (Some((path, bound_ident)), let_.expr()?) - } - _ => return None, // Unsupported IfLet. - } + (Some(let_.pat()?), let_.expr()?) } else { (None, cond) }; @@ -136,11 +121,10 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<' }; new_expr.syntax().clone_for_update() } - Some((path, bound_ident)) => { + Some(pat) => { // If-let. - let pat = make::tuple_struct_pat(path, once(bound_ident)); let let_else_stmt = make::let_else_stmt( - pat.into(), + pat, None, cond_expr, ast::make::tail_only_block_expr(early_expression), @@ -442,6 +426,60 @@ fn main() { ); } + #[test] + fn convert_arbitrary_if_let_patterns() { + check_assist( + convert_to_guarded_return, + r#" +fn main() { + $0if let None = Some(92) { + foo(); + } +} +"#, + r#" +fn main() { + let None = Some(92) else { return }; + foo(); +} +"#, + ); + + check_assist( + convert_to_guarded_return, + r#" +fn main() { + $0if let [1, x] = [1, 92] { + foo(x); + } +} +"#, + r#" +fn main() { + let [1, x] = [1, 92] else { return }; + foo(x); +} +"#, + ); + + check_assist( + convert_to_guarded_return, + r#" +fn main() { + $0if let (Some(x), None) = (Some(92), None) { + foo(x); + } +} +"#, + r#" +fn main() { + let (Some(x), None) = (Some(92), None) else { return }; + foo(x); +} +"#, + ); + } + #[test] fn ignore_already_converted_if() { check_assist_not_applicable( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs new file mode 100644 index 000000000000..32db5ee8dabf --- /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::()?; + let type_ref = ret_type.ty()?; + + let ast::Type::TupleType(tuple_ty) = &type_ref else { return None }; + if tuple_ty.fields().any(|field| matches!(field, ast::Type::ImplTraitType(_))) { + return None; + } + + let fn_ = ret_type.syntax().parent().and_then(ast::Fn::cast)?; + let fn_def = ctx.sema.to_def(&fn_)?; + let fn_name = fn_.name()?; + let target_module = ctx.sema.scope(fn_.syntax())?.module().nearest_non_block_module(ctx.db()); + + let target = type_ref.syntax().text_range(); + acc.add( + AssistId("convert_tuple_return_type_to_struct", AssistKind::RefactorRewrite), + "Convert tuple return type to tuple struct", + target, + move |edit| { + let ret_type = edit.make_mut(ret_type); + let fn_ = edit.make_mut(fn_); + + let usages = Definition::Function(fn_def).usages(&ctx.sema).all(); + let struct_name = format!("{}Result", stdx::to_camel_case(&fn_name.to_string())); + let parent = fn_.syntax().ancestors().find_map(>::cast); + add_tuple_struct_def( + edit, + ctx, + &usages, + parent.as_ref().map(|it| it.syntax()).unwrap_or(fn_.syntax()), + tuple_ty, + &struct_name, + &target_module, + ); + + ted::replace( + ret_type.syntax(), + make::ret_type(make::ty(&struct_name)).syntax().clone_for_update(), + ); + + if let Some(fn_body) = fn_.body() { + replace_body_return_values(ast::Expr::BlockExpr(fn_body), &struct_name); + } + + replace_usages(edit, ctx, &usages, &struct_name, &target_module); + }, + ) +} + +/// Replaces tuple usages with the corresponding tuple struct pattern. +fn replace_usages( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + struct_name: &str, + target_module: &hir::Module, +) { + for (file_id, references) in usages.iter() { + edit.edit_file(*file_id); + + let refs_with_imports = + augment_references_with_imports(edit, ctx, references, struct_name, target_module); + + refs_with_imports.into_iter().rev().for_each(|(name, import_data)| { + if let Some(fn_) = name.syntax().parent().and_then(ast::Fn::cast) { + cov_mark::hit!(replace_trait_impl_fns); + + if let Some(ret_type) = fn_.ret_type() { + ted::replace( + ret_type.syntax(), + make::ret_type(make::ty(struct_name)).syntax().clone_for_update(), + ); + } + + if let Some(fn_body) = fn_.body() { + replace_body_return_values(ast::Expr::BlockExpr(fn_body), struct_name); + } + } else { + // replace tuple patterns + let pats = name + .syntax() + .ancestors() + .find(|node| { + ast::CallExpr::can_cast(node.kind()) + || ast::MethodCallExpr::can_cast(node.kind()) + }) + .and_then(|node| node.parent()) + .and_then(node_to_pats) + .unwrap_or(Vec::new()); + + let tuple_pats = pats.iter().filter_map(|pat| match pat { + ast::Pat::TuplePat(tuple_pat) => Some(tuple_pat), + _ => None, + }); + for tuple_pat in tuple_pats { + ted::replace( + tuple_pat.syntax(), + make::tuple_struct_pat( + make::path_from_text(struct_name), + tuple_pat.fields(), + ) + .clone_for_update() + .syntax(), + ); + } + } + // add imports across modules where needed + if let Some((import_scope, path)) = import_data { + insert_use(&import_scope, path, &ctx.config.insert_use); + } + }) + } +} + +fn node_to_pats(node: SyntaxNode) -> Option> { + match_ast! { + match node { + ast::LetStmt(it) => it.pat().map(|pat| vec![pat]), + ast::LetExpr(it) => it.pat().map(|pat| vec![pat]), + ast::MatchExpr(it) => it.match_arm_list().map(|arm_list| { + arm_list.arms().filter_map(|arm| arm.pat()).collect() + }), + _ => None, + } + } +} + +fn augment_references_with_imports( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + references: &[FileReference], + struct_name: &str, + target_module: &hir::Module, +) -> Vec<(ast::NameLike, Option<(ImportScope, ast::Path)>)> { + let mut visited_modules = FxHashSet::default(); + + references + .iter() + .filter_map(|FileReference { name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| (name, scope.module())) + }) + .map(|(name, ref_module)| { + let new_name = edit.make_mut(name.clone()); + + // if the referenced module is not the same as the target one and has not been seen before, add an import + let import_data = if ref_module.nearest_non_block_module(ctx.db()) != *target_module + && !visited_modules.contains(&ref_module) + { + visited_modules.insert(ref_module); + + let import_scope = + ImportScope::find_insert_use_container(new_name.syntax(), &ctx.sema); + let path = ref_module + .find_use_path_prefixed( + ctx.sema.db, + ModuleDef::Module(*target_module), + ctx.config.insert_use.prefix_kind, + ctx.config.prefer_no_std, + ) + .map(|mod_path| { + make::path_concat( + mod_path_to_ast(&mod_path), + make::path_from_text(struct_name), + ) + }); + + import_scope.zip(path) + } else { + None + }; + + (new_name, import_data) + }) + .collect() +} + +// Adds the definition of the tuple struct before the parent function. +fn add_tuple_struct_def( + edit: &mut SourceChangeBuilder, + ctx: &AssistContext<'_>, + usages: &UsageSearchResult, + parent: &SyntaxNode, + tuple_ty: &ast::TupleType, + struct_name: &str, + target_module: &hir::Module, +) { + let make_struct_pub = usages + .iter() + .flat_map(|(_, refs)| refs) + .filter_map(|FileReference { name, .. }| { + ctx.sema.scope(name.syntax()).map(|scope| scope.module()) + }) + .any(|module| module.nearest_non_block_module(ctx.db()) != *target_module); + let visibility = if make_struct_pub { Some(make::visibility_pub()) } else { None }; + + let field_list = ast::FieldList::TupleFieldList(make::tuple_field_list( + tuple_ty.fields().map(|ty| make::tuple_field(visibility.clone(), ty)), + )); + let struct_name = make::name(struct_name); + let struct_def = make::struct_(visibility, struct_name, None, field_list).clone_for_update(); + + let indent = IndentLevel::from_node(parent); + struct_def.reindent_to(indent); + + edit.insert(parent.text_range().start(), format!("{struct_def}\n\n{indent}")); +} + +/// Replaces each returned tuple in `body` with the constructor of the tuple struct named `struct_name`. +fn replace_body_return_values(body: ast::Expr, struct_name: &str) { + let mut exprs_to_wrap = Vec::new(); + + let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_wrap, e); + walk_expr(&body, &mut |expr| { + if let ast::Expr::ReturnExpr(ret_expr) = expr { + if let Some(ret_expr_arg) = &ret_expr.expr() { + for_each_tail_expr(ret_expr_arg, tail_cb); + } + } + }); + for_each_tail_expr(&body, tail_cb); + + for ret_expr in exprs_to_wrap { + if let ast::Expr::TupleExpr(tuple_expr) = &ret_expr { + let struct_constructor = make::expr_call( + make::expr_path(make::ext::ident_path(struct_name)), + make::arg_list(tuple_expr.fields()), + ) + .clone_for_update(); + ted::replace(ret_expr.syntax(), struct_constructor.syntax()); + } + } +} + +fn tail_cb_impl(acc: &mut Vec, e: &ast::Expr) { + match e { + ast::Expr::BreakExpr(break_expr) => { + if let Some(break_expr_arg) = break_expr.expr() { + for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e)) + } + } + ast::Expr::ReturnExpr(_) => { + // all return expressions have already been handled by the walk loop + } + e => acc.push(e.clone()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::tests::{check_assist, check_assist_not_applicable}; + + #[test] + fn function_basic() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(&'static str, bool) { + ("bar", true) +} +"#, + r#" +struct BarResult(&'static str, bool); + +fn bar() -> BarResult { + BarResult("bar", true) +} +"#, + ) + } + + #[test] + fn struct_and_usages_indented() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +mod foo { + pub(crate) fn foo() { + let (bar, baz) = bar(); + println!("{bar} {baz}"); + } + + pub(crate) fn bar() -> $0(usize, bool) { + (42, true) + } +} +"#, + r#" +mod foo { + pub(crate) fn foo() { + let BarResult(bar, baz) = bar(); + println!("{bar} {baz}"); + } + + struct BarResult(usize, bool); + + pub(crate) fn bar() -> BarResult { + BarResult(42, true) + } +} +"#, + ) + } + + #[test] + fn field_usage() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + let bar_result = bar(); + println!("{} {}", bar_result.1, bar().0); +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + let bar_result = bar(); + println!("{} {}", bar_result.1, bar().0); +} +"#, + ) + } + + #[test] + fn method_usage() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +struct Foo; + +impl Foo { + fn foo(&self, x: usize) -> $0(usize, usize) { + (x, x) + } +} + +fn main() { + let foo = Foo {}; + let (x, y) = foo.foo(2); +} +"#, + r#" +struct Foo; + +struct FooResult(usize, usize); + +impl Foo { + fn foo(&self, x: usize) -> FooResult { + FooResult(x, x) + } +} + +fn main() { + let foo = Foo {}; + let FooResult(x, y) = foo.foo(2); +} +"#, + ) + } + + #[test] + fn method_usage_within_same_impl() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +struct Foo; + +impl Foo { + fn new() -> $0(usize, usize) { + (0, 0) + } + + fn foo() { + let (mut foo1, mut foo2) = Self::new(); + } +} +"#, + r#" +struct Foo; + +struct NewResult(usize, usize); + +impl Foo { + fn new() -> NewResult { + NewResult(0, 0) + } + + fn foo() { + let NewResult(mut foo1, mut foo2) = Self::new(); + } +} +"#, + ) + } + + #[test] + fn multiple_usages() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, usize) { + (42, 24) +} + +fn main() { + let bar_result = bar(); + let (foo, b) = bar(); + let (b, baz) = bar(); + + if foo == b && b == baz { + println!("{} {}", bar_result.1, bar().0); + } +} +"#, + r#" +struct BarResult(usize, usize); + +fn bar() -> BarResult { + BarResult(42, 24) +} + +fn main() { + let bar_result = bar(); + let BarResult(foo, b) = bar(); + let BarResult(b, baz) = bar(); + + if foo == b && b == baz { + println!("{} {}", bar_result.1, bar().0); + } +} +"#, + ) + } + + #[test] + fn usage_match_tuple_pat() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + match bar() { + x if x.0 == 0 => println!("0"), + (x, false) => println!("{x}"), + (42, true) => println!("bar"), + _ => println!("foo"), + } +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + match bar() { + x if x.0 == 0 => println!("0"), + BarResult(x, false) => println!("{x}"), + BarResult(42, true) => println!("bar"), + _ => println!("foo"), + } +} +"#, + ) + } + + #[test] + fn usage_if_let_tuple_pat() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + if let (42, true) = bar() { + println!("bar") + } +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + if let BarResult(42, true) = bar() { + println!("bar") + } +} +"#, + ) + } + + #[test] + fn function_nested_outer() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + fn foo() -> (usize, bool) { + (42, true) + } + + foo() +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + fn foo() -> (usize, bool) { + (42, true) + } + + foo() +} +"#, + ) + } + + #[test] + fn function_nested_inner() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> (usize, bool) { + fn foo() -> $0(usize, bool) { + (42, true) + } + + foo() +} +"#, + r#" +fn bar() -> (usize, bool) { + struct FooResult(usize, bool); + + fn foo() -> FooResult { + FooResult(42, true) + } + + foo() +} +"#, + ) + } + + #[test] + fn trait_impl_and_usage() { + cov_mark::check!(replace_trait_impl_fns); + check_assist( + convert_tuple_return_type_to_struct, + r#" +struct Struct; + +trait Foo { + fn foo(&self) -> $0(usize, bool); +} + +impl Foo for Struct { + fn foo(&self) -> (usize, bool) { + (0, true) + } +} + +fn main() { + let s = Struct {}; + let (foo, bar) = s.foo(); + let (foo, bar) = Struct::foo(&s); + println!("{foo} {bar}"); +} +"#, + r#" +struct Struct; + +struct FooResult(usize, bool); + +trait Foo { + fn foo(&self) -> FooResult; +} + +impl Foo for Struct { + fn foo(&self) -> FooResult { + FooResult(0, true) + } +} + +fn main() { + let s = Struct {}; + let FooResult(foo, bar) = s.foo(); + let FooResult(foo, bar) = Struct::foo(&s); + println!("{foo} {bar}"); +} +"#, + ) + } + + #[test] + fn body_wraps_nested() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn foo() -> $0(u8, usize, u32) { + if true { + match 3 { + 0 => (1, 2, 3), + _ => return (4, 5, 6), + } + } else { + (2, 1, 3) + } +} +"#, + r#" +struct FooResult(u8, usize, u32); + +fn foo() -> FooResult { + if true { + match 3 { + 0 => FooResult(1, 2, 3), + _ => return FooResult(4, 5, 6), + } + } else { + FooResult(2, 1, 3) + } +} +"#, + ) + } + + #[test] + fn body_wraps_break_and_return() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn foo(mut i: isize) -> (usize, $0u32, u8) { + if i < 0 { + return (0, 0, 0); + } + + loop { + if i == 2 { + println!("foo"); + break (1, 2, 3); + } + i += 1; + } +} +"#, + r#" +struct FooResult(usize, u32, u8); + +fn foo(mut i: isize) -> FooResult { + if i < 0 { + return FooResult(0, 0, 0); + } + + loop { + if i == 2 { + println!("foo"); + break FooResult(1, 2, 3); + } + i += 1; + } +} +"#, + ) + } + + #[test] + fn body_doesnt_wrap_identifier() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn foo() -> $0(u8, usize, u32) { + let tuple = (1, 2, 3); + tuple +} +"#, + r#" +struct FooResult(u8, usize, u32); + +fn foo() -> FooResult { + let tuple = (1, 2, 3); + tuple +} +"#, + ) + } + + #[test] + fn body_doesnt_wrap_other_exprs() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar(num: usize) -> (u8, usize, u32) { + (1, num, 3) +} + +fn foo() -> $0(u8, usize, u32) { + bar(2) +} +"#, + r#" +fn bar(num: usize) -> (u8, usize, u32) { + (1, num, 3) +} + +struct FooResult(u8, usize, u32); + +fn foo() -> FooResult { + bar(2) +} +"#, + ) + } + + #[test] + fn cross_file_and_module() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +//- /main.rs +mod foo; + +fn main() { + use foo::bar; + + let (bar, baz) = bar::bar(); + println!("{}", bar == baz); +} + +//- /foo.rs +pub mod bar { + pub fn bar() -> $0(usize, usize) { + (1, 3) + } +} +"#, + r#" +//- /main.rs +use crate::foo::bar::BarResult; + +mod foo; + +fn main() { + use foo::bar; + + let BarResult(bar, baz) = bar::bar(); + println!("{}", bar == baz); +} + +//- /foo.rs +pub mod bar { + pub struct BarResult(pub usize, pub usize); + + pub fn bar() -> BarResult { + BarResult(1, 3) + } +} +"#, + ) + } + + #[test] + fn does_not_replace_nested_usage() { + check_assist( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(usize, bool) { + (42, true) +} + +fn main() { + let ((bar1, bar2), foo) = (bar(), 3); + println!("{bar1} {bar2} {foo}"); +} +"#, + r#" +struct BarResult(usize, bool); + +fn bar() -> BarResult { + BarResult(42, true) +} + +fn main() { + let ((bar1, bar2), foo) = (bar(), 3); + println!("{bar1} {bar2} {foo}"); +} +"#, + ) + } + + #[test] + fn function_with_non_tuple_return_type() { + check_assist_not_applicable( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0usize { + 0 +} +"#, + ) + } + + #[test] + fn function_with_impl_type() { + check_assist_not_applicable( + convert_tuple_return_type_to_struct, + r#" +fn bar() -> $0(impl Clone, usize) { + ("bar", 0) +} +"#, + ) + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs index ddc8a50ed400..c859e98524e8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs @@ -33,9 +33,7 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> // Only allow comments which are alone on their line if let Some(prev) = comment.syntax().prev_token() { - if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() { - return None; - } + Whitespace::cast(prev).filter(|w| w.text().contains('\n'))?; } let indentation = IndentLevel::from_token(comment.syntax()).to_string(); @@ -50,7 +48,7 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> ( TextRange::new( comments[0].syntax().text_range().start(), - comments.last().unwrap().syntax().text_range().end(), + comments.last()?.syntax().text_range().end(), ), Either::Right(comments), ) @@ -71,9 +69,11 @@ pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> .map(|l| l.strip_prefix(&indentation).unwrap_or(l)) .join("\n") } - Either::Right(comments) => { - comments.into_iter().map(|c| line_comment_text(IndentLevel(0), c)).join("\n") - } + Either::Right(comments) => comments + .into_iter() + .map(|cm| line_comment_text(IndentLevel(0), cm)) + .collect::>() + .join("\n"), }; let hashes = "#".repeat(required_hashes(&text)); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs index 014c23197fac..e7c884dcb706 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs @@ -29,22 +29,31 @@ use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; // } // ``` pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - if ctx.has_empty_selection() { - return None; - } - - let node = match ctx.covering_element() { - NodeOrToken::Node(it) => it, - NodeOrToken::Token(it) if it.kind() == COMMENT => { - cov_mark::hit!(extract_var_in_comment_is_not_applicable); + let node = if ctx.has_empty_selection() { + if let Some(expr_stmt) = ctx.find_node_at_offset::() { + expr_stmt.syntax().clone() + } else if let Some(expr) = ctx.find_node_at_offset::() { + expr.syntax().ancestors().find_map(valid_target_expr)?.syntax().clone() + } else { return None; } - NodeOrToken::Token(it) => it.parent()?, + } else { + match ctx.covering_element() { + NodeOrToken::Node(it) => it, + NodeOrToken::Token(it) if it.kind() == COMMENT => { + cov_mark::hit!(extract_var_in_comment_is_not_applicable); + return None; + } + NodeOrToken::Token(it) => it.parent()?, + } }; + let node = node.ancestors().take_while(|anc| anc.text_range() == node.text_range()).last()?; + let range = node.text_range(); + let to_extract = node .descendants() - .take_while(|it| ctx.selection_trimmed().contains_range(it.text_range())) + .take_while(|it| range.contains_range(it.text_range())) .find_map(valid_target_expr)?; let ty = ctx.sema.type_of_expr(&to_extract).map(TypeInfo::adjusted); @@ -235,6 +244,138 @@ mod tests { use super::*; + #[test] + fn test_extract_var_simple_without_select() { + check_assist( + extract_variable, + r#" +fn main() -> i32 { + if true { + 1 + } else { + 2 + }$0 +} +"#, + r#" +fn main() -> i32 { + let $0var_name = if true { + 1 + } else { + 2 + }; + var_name +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn foo() -> i32 { 1 } +fn main() { + foo();$0 +} +"#, + r#" +fn foo() -> i32 { 1 } +fn main() { + let $0foo = foo(); +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + let a = Some(2); + a.is_some();$0 +} +"#, + r#" +fn main() { + let a = Some(2); + let $0is_some = a.is_some(); +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + "hello"$0; +} +"#, + r#" +fn main() { + let $0var_name = "hello"; +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + 1 + 2$0; +} +"#, + r#" +fn main() { + let $0var_name = 1 + 2; +} +"#, + ); + + check_assist( + extract_variable, + r#" +fn main() { + match () { + () if true => 1, + _ => 2, + };$0 +} +"#, + r#" +fn main() { + let $0var_name = match () { + () if true => 1, + _ => 2, + }; +} +"#, + ); + } + + #[test] + fn test_extract_var_unit_expr_without_select_not_applicable() { + check_assist_not_applicable( + extract_variable, + r#" +fn foo() {} +fn main() { + foo()$0; +} +"#, + ); + + check_assist_not_applicable( + extract_variable, + r#" +fn foo() { + let mut i = 3; + if i >= 0 { + i += 1; + } else { + i -= 1; + }$0 +}"#, + ); + } + #[test] fn test_extract_var_simple() { check_assist( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs index 5b13e01b1330..f74fc5df4bd2 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 000000000000..cb8ef395650b --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs @@ -0,0 +1,202 @@ +use ide_db::famous_defs::FamousDefs; +use syntax::{ + ast::{self, make}, + ted, AstNode, +}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// FIXME: Generate proper `index_mut` method body refer to `index` method body may impossible due to the unpredicable case [#15581]. +// Here just leave the `index_mut` method body be same as `index` method body, user can modify it manually to meet their need. + +// Assist: generate_mut_trait_impl +// +// Adds a IndexMut impl from the `Index` trait. +// +// ``` +// # //- minicore: index +// pub enum Axis { X = 0, Y = 1, Z = 2 } +// +// impl core::ops::Index$0 for [T; 3] { +// type Output = T; +// +// fn index(&self, index: Axis) -> &Self::Output { +// &self[index as usize] +// } +// } +// ``` +// -> +// ``` +// pub enum Axis { X = 0, Y = 1, Z = 2 } +// +// $0impl core::ops::IndexMut for [T; 3] { +// fn index_mut(&mut self, index: Axis) -> &mut Self::Output { +// &self[index as usize] +// } +// } +// +// impl core::ops::Index for [T; 3] { +// type Output = T; +// +// fn index(&self, index: Axis) -> &Self::Output { +// &self[index as usize] +// } +// } +// ``` +pub(crate) fn generate_mut_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let impl_def = ctx.find_node_at_offset::()?.clone_for_update(); + + let trait_ = impl_def.trait_()?; + if let ast::Type::PathType(trait_path) = trait_.clone() { + let trait_type = ctx.sema.resolve_trait(&trait_path.path()?)?; + let scope = ctx.sema.scope(trait_path.syntax())?; + if trait_type != FamousDefs(&ctx.sema, scope.krate()).core_convert_Index()? { + return None; + } + } + + // Index -> IndexMut + let index_trait = impl_def + .syntax() + .descendants() + .filter_map(ast::NameRef::cast) + .find(|it| it.text() == "Index")?; + ted::replace( + index_trait.syntax(), + make::path_segment(make::name_ref("IndexMut")).clone_for_update().syntax(), + ); + + // index -> index_mut + let trait_method_name = impl_def + .syntax() + .descendants() + .filter_map(ast::Name::cast) + .find(|it| it.text() == "index")?; + ted::replace(trait_method_name.syntax(), make::name("index_mut").clone_for_update().syntax()); + + let type_alias = impl_def.syntax().descendants().find_map(ast::TypeAlias::cast)?; + ted::remove(type_alias.syntax()); + + // &self -> &mut self + let mut_self_param = make::mut_self_param(); + let self_param: ast::SelfParam = + impl_def.syntax().descendants().find_map(ast::SelfParam::cast)?; + ted::replace(self_param.syntax(), mut_self_param.clone_for_update().syntax()); + + // &Self::Output -> &mut Self::Output + let ret_type = impl_def.syntax().descendants().find_map(ast::RetType::cast)?; + ted::replace( + ret_type.syntax(), + make::ret_type(make::ty("&mut Self::Output")).clone_for_update().syntax(), + ); + + let fn_ = impl_def.assoc_item_list()?.assoc_items().find_map(|it| match it { + ast::AssocItem::Fn(f) => Some(f), + _ => None, + })?; + + let assoc_list = make::assoc_item_list().clone_for_update(); + assoc_list.add_item(syntax::ast::AssocItem::Fn(fn_)); + ted::replace(impl_def.assoc_item_list()?.syntax(), assoc_list.syntax()); + + let target = impl_def.syntax().text_range(); + acc.add( + AssistId("generate_mut_trait_impl", AssistKind::Generate), + "Generate `IndexMut` impl from this `Index` trait", + target, + |edit| { + edit.insert(target.start(), format!("$0{}\n\n", impl_def.to_string())); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn test_generate_mut_trait_impl() { + check_assist( + generate_mut_trait_impl, + r#" +//- minicore: index +pub enum Axis { X = 0, Y = 1, Z = 2 } + +impl core::ops::Index$0 for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#, + r#" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +$0impl core::ops::IndexMut for [T; 3] { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + &self[index as usize] + } +} + +impl core::ops::Index for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#, + ); + + check_assist( + generate_mut_trait_impl, + r#" +//- minicore: index +pub enum Axis { X = 0, Y = 1, Z = 2 } + +impl core::ops::Index$0 for [T; 3] where T: Copy { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + let var_name = &self[index as usize]; + var_name + } +} +"#, + r#" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +$0impl core::ops::IndexMut for [T; 3] where T: Copy { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + let var_name = &self[index as usize]; + var_name + } +} + +impl core::ops::Index for [T; 3] where T: Copy { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + let var_name = &self[index as usize]; + var_name + } +} +"#, + ); + } + + #[test] + fn test_generate_mut_trait_impl_not_applicable() { + check_assist_not_applicable( + generate_mut_trait_impl, + r#" +pub trait Index {} + +impl Index$0 for [T; 3] {} +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs index ffab58509b18..f8c75bdb0de1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs @@ -224,7 +224,6 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option< syntax.text_range(), |builder| { let replacement = inline(&ctx.sema, file_id, function, &fn_body, ¶ms, &call_info); - builder.replace_ast( match call_info.node { ast::CallableExpr::Call(it) => ast::Expr::CallExpr(it), @@ -363,16 +362,22 @@ fn inline( .collect(); if function.self_param(sema.db).is_some() { - let this = || make::name_ref("this").syntax().clone_for_update().first_token().unwrap(); + let this = || { + make::name_ref("this") + .syntax() + .clone_for_update() + .first_token() + .expect("NameRef should have had a token.") + }; if let Some(self_local) = params[0].2.as_local(sema.db) { usages_for_locals(self_local) .filter_map(|FileReference { name, range, .. }| match name { ast::NameLike::NameRef(_) => Some(body.syntax().covering_element(range)), _ => None, }) - .for_each(|it| { - ted::replace(it, &this()); - }) + .for_each(|usage| { + ted::replace(usage, &this()); + }); } } @@ -470,7 +475,9 @@ fn inline( } } else if let Some(stmt_list) = body.stmt_list() { ted::insert_all( - ted::Position::after(stmt_list.l_curly_token().unwrap()), + ted::Position::after( + stmt_list.l_curly_token().expect("L_CURLY for StatementList is missing."), + ), let_stmts.into_iter().map(|stmt| stmt.syntax().clone().into()).collect(), ); } @@ -481,8 +488,12 @@ fn inline( }; body.reindent_to(original_indentation); + let no_stmts = body.statements().next().is_none(); match body.tail_expr() { - Some(expr) if !is_async_fn && body.statements().next().is_none() => expr, + Some(expr) if matches!(expr, ast::Expr::ClosureExpr(_)) && no_stmts => { + make::expr_paren(expr).clone_for_update() + } + Some(expr) if !is_async_fn && no_stmts => expr, _ => match node .syntax() .parent() @@ -1471,6 +1482,31 @@ fn main() { } }); } +"#, + ); + } + + #[test] + fn inline_call_closure_body() { + check_assist( + inline_call, + r#" +fn f() -> impl Fn() -> i32 { + || 2 +} + +fn main() { + let _ = $0f()(); +} +"#, + r#" +fn f() -> impl Fn() -> i32 { + || 2 +} + +fn main() { + let _ = (|| 2)(); +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs index e69d1a29677a..49dcde75d2b3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs @@ -96,8 +96,7 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>) ); let parent = matches!( usage_parent, - ast::Expr::CallExpr(_) - | ast::Expr::TupleExpr(_) + ast::Expr::TupleExpr(_) | ast::Expr::ArrayExpr(_) | ast::Expr::ParenExpr(_) | ast::Expr::ForExpr(_) @@ -949,6 +948,24 @@ fn f() { let S$0 = S; S; } +"#, + ); + } + + #[test] + fn test_inline_closure() { + check_assist( + inline_local_variable, + r#" +fn main() { + let $0f = || 2; + let _ = f(); +} +"#, + r#" +fn main() { + let _ = (|| 2)(); +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs index 663df266b6f8..965e4aa786e7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs @@ -52,9 +52,13 @@ pub(crate) fn into_to_qualified_from(acc: &mut Assists, ctx: &AssistContext<'_>) == FamousDefs(sema, scope.krate()).core_convert_Into()? { let type_call = sema.type_of_expr(&method_call.clone().into())?; - let type_call_disp = - type_call.adjusted().display_source_code(db, scope.module().into(), true).ok()?; + let adjusted_tc = type_call.adjusted(); + if adjusted_tc.contains_unknown() { + return None; + } + + let sc = adjusted_tc.display_source_code(db, scope.module().into(), true).ok()?; acc.add( AssistId("into_to_qualified_from", AssistKind::Generate), "Convert `into` to fully qualified `from`", @@ -62,7 +66,11 @@ pub(crate) fn into_to_qualified_from(acc: &mut Assists, ctx: &AssistContext<'_>) |edit| { edit.replace( method_call.syntax().text_range(), - format!("{}::from({})", type_call_disp, receiver), + if sc.chars().all(|c| c.is_alphanumeric() || c == ':') { + format!("{}::from({})", sc, receiver) + } else { + format!("<{}>::from({})", sc, receiver) + }, ); }, ); @@ -199,6 +207,66 @@ mod C { fn main() -> () { let a: A = A; let b: C::B = C::B::from(a); +}"#, + ) + } + + #[test] + fn preceding_type_qualifier() { + check_assist( + into_to_qualified_from, + r#" +//- minicore: from +impl From<(i32,i32)> for [i32;2] { + fn from(value: (i32,i32)) -> Self { + [value.0, value.1] + } +} + +fn tuple_to_array() -> [i32; 2] { + (0,1).in$0to() +}"#, + r#" +impl From<(i32,i32)> for [i32;2] { + fn from(value: (i32,i32)) -> Self { + [value.0, value.1] + } +} + +fn tuple_to_array() -> [i32; 2] { + <[i32; 2]>::from((0,1)) +}"#, + ) + } + + #[test] + fn type_with_gens() { + check_assist( + into_to_qualified_from, + r#" +//- minicore: from +struct StructA(Gen); + +impl From for StructA { + fn from(value: i32) -> Self { + StructA(value + 1) + } +} + +fn main() -> () { + let a: StructA = 3.in$0to(); +}"#, + r#" +struct StructA(Gen); + +impl From for StructA { + fn from(value: i32) -> Self { + StructA(value + 1) + } +} + +fn main() -> () { + let a: StructA = >::from(3); }"#, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/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 000000000000..b1daaea1ed1b --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs @@ -0,0 +1,172 @@ +use syntax::ast::{self, AstNode}; + +use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; + +// Assist: replace_is_some_with_if_let_some +// +// Replace `if x.is_some()` with `if let Some(_tmp) = x` or `if x.is_ok()` with `if let Ok(_tmp) = x`. +// +// ``` +// fn main() { +// let x = Some(1); +// if x.is_som$0e() {} +// } +// ``` +// -> +// ``` +// fn main() { +// let x = Some(1); +// if let Some(${0:x}) = x {} +// } +// ``` +pub(crate) fn replace_is_method_with_if_let_method( + acc: &mut Assists, + ctx: &AssistContext<'_>, +) -> Option<()> { + let if_expr = ctx.find_node_at_offset::()?; + + let cond = if_expr.condition()?; + let call_expr = match cond { + ast::Expr::MethodCallExpr(call) => call, + _ => return None, + }; + + let name_ref = call_expr.name_ref()?; + match name_ref.text().as_str() { + "is_some" | "is_ok" => { + let receiver = call_expr.receiver()?; + + let var_name = if let ast::Expr::PathExpr(path_expr) = receiver.clone() { + path_expr.path()?.to_string() + } else { + suggest_name::for_variable(&receiver, &ctx.sema) + }; + + let target = call_expr.syntax().text_range(); + + let (assist_id, message, text) = if name_ref.text() == "is_some" { + ("replace_is_some_with_if_let_some", "Replace `is_some` with `if let Some`", "Some") + } else { + ("replace_is_ok_with_if_let_ok", "Replace `is_ok` with `if let Ok`", "Ok") + }; + + acc.add(AssistId(assist_id, AssistKind::RefactorRewrite), message, target, |edit| { + let var_name = format!("${{0:{}}}", var_name); + let replacement = format!("let {}({}) = {}", text, var_name, receiver); + edit.replace(target, replacement); + }) + } + _ => return None, + } +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::replace_is_method_with_if_let_method; + + #[test] + fn replace_is_some_with_if_let_some_works() { + check_assist( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Some(1); + if x.is_som$0e() {} +} +"#, + r#" +fn main() { + let x = Some(1); + if let Some(${0:x}) = x {} +} +"#, + ); + + check_assist( + replace_is_method_with_if_let_method, + r#" +fn test() -> Option { + Some(1) +} +fn main() { + if test().is_som$0e() {} +} +"#, + r#" +fn test() -> Option { + Some(1) +} +fn main() { + if let Some(${0:test}) = test() {} +} +"#, + ); + } + + #[test] + fn replace_is_some_with_if_let_some_not_applicable() { + check_assist_not_applicable( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Some(1); + if x.is_non$0e() {} +} +"#, + ); + } + + #[test] + fn replace_is_ok_with_if_let_ok_works() { + check_assist( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Ok(1); + if x.is_o$0k() {} +} +"#, + r#" +fn main() { + let x = Ok(1); + if let Ok(${0:x}) = x {} +} +"#, + ); + + check_assist( + replace_is_method_with_if_let_method, + r#" +fn test() -> Result { + Ok(1) +} +fn main() { + if test().is_o$0k() {} +} +"#, + r#" +fn test() -> Result { + Ok(1) +} +fn main() { + if let Ok(${0:test}) = test() {} +} +"#, + ); + } + + #[test] + fn replace_is_ok_with_if_let_ok_not_applicable() { + check_assist_not_applicable( + replace_is_method_with_if_let_method, + r#" +fn main() { + let x = Ok(1); + if x.is_e$0rr() {} +} +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs index dac216b69b72..52df30d9623f 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(); + 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()); + tree.remove(); + ted::insert(Position::after(use_.syntax()), new_use.syntax()); - builder.replace(old_parent_range, new_parent.to_string()); - }, - ) + builder.replace(old_parent_range, new_parent.to_string()); + }) } fn resolve_full_path(tree: &ast::UseTree) -> Option { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs index e9d4e270cdcf..0bf1782a489d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs @@ -1,3 +1,4 @@ +use ide_db::imports::insert_use::ImportScope; use syntax::{ ast::{self, make, AstNode, HasArgList}, TextRange, @@ -17,6 +18,8 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // ``` // -> // ``` +// use std::ops::Add; +// // fn main() { // 1.add(2); // } @@ -38,7 +41,7 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) let first_arg = args_iter.next()?; let second_arg = args_iter.next(); - _ = path.qualifier()?; + let qualifier = path.qualifier()?; let method_name = path.segment()?.name_ref()?; let res = ctx.sema.resolve_path(&path)?; @@ -76,10 +79,51 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) edit.insert(close, ")"); } edit.replace(replace_comma, format!(".{method_name}(")); + add_import(qualifier, ctx, edit); }, ) } +fn add_import( + qualifier: ast::Path, + ctx: &AssistContext<'_>, + edit: &mut ide_db::source_change::SourceChangeBuilder, +) { + if let Some(path_segment) = qualifier.segment() { + // for `` + let path_type = path_segment.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() { ::$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 f235b554e61f..03e6dfebebfb 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_result_return_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_result_return_type.rs @@ -123,10 +123,8 @@ fn tail_cb_impl(acc: &mut Vec, e: &ast::Expr) { for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e)) } } - Expr::ReturnExpr(ret_expr) => { - if let Some(ret_expr_arg) = &ret_expr.expr() { - for_each_tail_expr(ret_expr_arg, &mut |e| tail_cb_impl(acc, e)); - } + Expr::ReturnExpr(_) => { + // all return expressions have already been handled by the walk loop } e => acc.push(e.clone()), } @@ -800,6 +798,24 @@ fn foo() -> i32 { ); } + #[test] + fn wrap_return_in_tail_position() { + check_assist( + unwrap_result_return_type, + r#" +//- minicore: result +fn foo(num: i32) -> $0Result { + return Ok(num) +} +"#, + r#" +fn foo(num: i32) -> i32 { + return num +} +"#, + ); + } + #[test] fn unwrap_result_return_type_simple_with_closure() { check_assist( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs index 61e9bcdcc516..b68ed00f7721 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs @@ -98,10 +98,8 @@ fn tail_cb_impl(acc: &mut Vec, e: &ast::Expr) { for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e)) } } - Expr::ReturnExpr(ret_expr) => { - if let Some(ret_expr_arg) = &ret_expr.expr() { - for_each_tail_expr(ret_expr_arg, &mut |e| tail_cb_impl(acc, e)); - } + Expr::ReturnExpr(_) => { + // all return expressions have already been handled by the walk loop } e => acc.push(e.clone()), } @@ -732,6 +730,24 @@ fn foo() -> Result { ); } + #[test] + fn wrap_return_in_tail_position() { + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +fn foo(num: i32) -> $0i32 { + return num +} +"#, + r#" +fn foo(num: i32) -> Result { + return Ok(num) +} +"#, + ); + } + #[test] fn wrap_return_type_in_result_simple_with_closure() { check_assist( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index 6f973ab53eec..e6f03214ed30 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 dfaa53449f42..da5822bba9c8 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -244,6 +244,30 @@ fn main() { ) } +#[test] +fn doctest_apply_demorgan_iterator() { + check_doc_test( + "apply_demorgan_iterator", + r#####" +//- minicore: iterator +fn main() { + let arr = [1, 2, 3]; + if !arr.into_iter().$0any(|num| num == 4) { + println!("foo"); + } +} +"#####, + r#####" +fn main() { + let arr = [1, 2, 3]; + if arr.into_iter().all(|num| num != 4) { + println!("foo"); + } +} +"#####, + ) +} + #[test] fn doctest_auto_import() { check_doc_test( @@ -280,6 +304,34 @@ fn some_function(x: i32) { ) } +#[test] +fn doctest_bool_to_enum() { + check_doc_test( + "bool_to_enum", + r#####" +fn main() { + let $0bool = true; + + if bool { + println!("foo"); + } +} +"#####, + r#####" +#[derive(PartialEq, Eq)] +enum Bool { True, False } + +fn main() { + let bool = Bool::True; + + if bool == Bool::True { + println!("foo"); + } +} +"#####, + ) +} + #[test] fn doctest_change_visibility() { check_doc_test( @@ -558,6 +610,33 @@ fn main() { ) } +#[test] +fn doctest_convert_tuple_return_type_to_struct() { + check_doc_test( + "convert_tuple_return_type_to_struct", + r#####" +fn bar() { + let (a, b, c) = foo(); +} + +fn foo() -> ($0u32, u32, u32) { + (1, 2, 3) +} +"#####, + r#####" +fn bar() { + let FooResult(a, b, c) = foo(); +} + +struct FooResult(u32, u32, u32); + +fn foo() -> FooResult { + FooResult(1, 2, 3) +} +"#####, + ) +} + #[test] fn doctest_convert_tuple_struct_to_named_struct() { check_doc_test( @@ -1459,6 +1538,42 @@ impl MyStruct { ) } +#[test] +fn doctest_generate_mut_trait_impl() { + check_doc_test( + "generate_mut_trait_impl", + r#####" +//- minicore: index +pub enum Axis { X = 0, Y = 1, Z = 2 } + +impl core::ops::Index$0 for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#####, + r#####" +pub enum Axis { X = 0, Y = 1, Z = 2 } + +$0impl core::ops::IndexMut for [T; 3] { + fn index_mut(&mut self, index: Axis) -> &mut Self::Output { + &self[index as usize] + } +} + +impl core::ops::Index for [T; 3] { + type Output = T; + + fn index(&self, index: Axis) -> &Self::Output { + &self[index as usize] + } +} +"#####, + ) +} + #[test] fn doctest_generate_new() { check_doc_test( @@ -2479,6 +2594,25 @@ fn handle(action: Action) { ) } +#[test] +fn doctest_replace_is_some_with_if_let_some() { + check_doc_test( + "replace_is_some_with_if_let_some", + r#####" +fn main() { + let x = Some(1); + if x.is_som$0e() {} +} +"#####, + r#####" +fn main() { + let x = Some(1); + if let Some(${0:x}) = x {} +} +"#####, + ) +} + #[test] fn doctest_replace_let_with_if_let() { check_doc_test( @@ -2850,6 +2984,8 @@ fn main() { mod std { pub mod ops { pub trait Add { fn add(self, _: Self) {} } impl Add for i32 {} } } "#####, r#####" +use std::ops::Add; + fn main() { 1.add(2); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs index 39c1b7f7b3fb..0961021e48e0 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 8f6a97e1e09d..3d025f284bbb 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, pub snippet_cap: Option, 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 c45cc8d7b37e..ed74ef7b667b 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 2eaa42040a01..2fad293d16d7 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 8afce8db5ea8..dfae715afe36 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 2464e8d5f817..284bdd8af21f 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 4cdfd546f6ad..21f693d79f1d 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 e80a289049f1..d3dbd7cc2277 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -2,10 +2,15 @@ use expect_test::{expect, Expect}; -use crate::tests::{ - check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character, +use crate::{ + tests::{ + check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character, + }, + CompletionItemKind, }; +use super::{do_completion_with_config, TEST_CONFIG}; + fn check_no_kw(ra_fixture: &str, expect: Expect) { let actual = completion_list_no_kw(ra_fixture); expect.assert_eq(&actual) @@ -1303,3 +1308,176 @@ struct Foo(x: &'x mut T) -> u8 where T: Clone, { 0u8 } +fn main() { fo$0 } +"#, + CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function), + expect!("fn(&mut T) -> u8"), + expect!("pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone,"), + ); + + check_signatures( + r#" +struct Foo; +struct Bar; +impl Bar { + pub const fn baz(x: Foo) -> ! { loop {} }; +} + +fn main() { Bar::b$0 } +"#, + CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function), + expect!("const fn(Foo) -> !"), + expect!("pub const fn baz(x: Foo) -> !"), + ); + + check_signatures( + r#" +struct Foo; +struct Bar; +impl Bar { + pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> ! { loop {} }; +} + +fn main() { + let mut bar = Bar; + bar.b$0 +} +"#, + CompletionItemKind::Method, + expect!("const fn(&'foo mut self, &Foo) -> !"), + expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"), + ); +} + +#[test] +fn skips_underscore() { + check_with_trigger_character( + r#" +fn foo(_$0) { } +"#, + Some('_'), + expect![[r#""#]], + ); + check_with_trigger_character( + r#" +fn foo(_: _$0) { } +"#, + Some('_'), + expect![[r#""#]], + ); + check_with_trigger_character( + r#" +fn foo() { + foo::<_$0>(); +} +"#, + Some('_'), + expect![[r#""#]], + ); + // underscore expressions are fine, they are invalid so the user definitely meant to type an + // underscored name here + check_with_trigger_character( + r#" +fn foo() { + _$0 +} +"#, + Some('_'), + expect![[r#" + fn foo() fn() + bt u32 + kw const + kw crate:: + kw enum + kw extern + kw false + kw fn + kw for + kw if + kw if let + kw impl + kw let + kw loop + kw match + kw mod + kw return + kw self:: + kw static + kw struct + kw trait + kw true + kw type + kw union + kw unsafe + kw use + kw while + kw while let + sn macro_rules + sn pd + sn ppd + "#]], + ); +} + +#[test] +fn no_skip_underscore_ident() { + check_with_trigger_character( + r#" +fn foo(a_$0) { } +"#, + Some('_'), + expect![[r#" + kw mut + kw ref + "#]], + ); + check_with_trigger_character( + r#" +fn foo(_: a_$0) { } +"#, + Some('_'), + expect![[r#" + bt u32 + kw crate:: + kw self:: + "#]], + ); + check_with_trigger_character( + r#" +fn foo() { + foo::(); +} +"#, + Some('_'), + expect![[r#" + tp T + bt u32 + kw crate:: + kw self:: + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index 4ce80532e8ef..ef72fc3861a7 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 b63dde2c21e7..722517a7677b 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs @@ -54,6 +54,10 @@ impl FamousDefs<'_, '_> { self.find_trait("core:convert:Into") } + pub fn core_convert_Index(&self) -> Option { + self.find_trait("core:ops:Index") + } + pub fn core_option_Option(&self) -> Option { self.find_enum("core:option:Option") } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index 57563a174833..1cb6ff8627a2 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -9,12 +9,18 @@ pub struct LintGroup { pub lint: Lint, pub children: &'static [&'static str], } + pub const DEFAULT_LINTS: &[Lint] = &[ Lint { label: "absolute_paths_not_starting_with_crate", description: r##"fully qualified paths that start with a module name instead of `crate`, `self`, or an extern crate name"##, }, Lint { label: "ambiguous_associated_items", description: r##"ambiguous associated items"## }, + Lint { + label: "ambiguous_glob_imports", + description: r##"detects certain glob imports that require reporting an ambiguity error"##, + }, + Lint { label: "ambiguous_glob_reexports", description: r##"ambiguous glob re-exports"## }, Lint { label: "anonymous_parameters", description: r##"detects anonymous parameters"## }, Lint { label: "arithmetic_overflow", description: r##"arithmetic operation overflows"## }, Lint { @@ -25,6 +31,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "asm_sub_register", description: r##"using only a subset of a register for inline asm inputs"##, }, + Lint { + label: "async_fn_in_trait", + description: r##"use of `async fn` in definition of a publicly-reachable trait"##, + }, Lint { label: "bad_asm_style", description: r##"incorrect use of inline assembly"## }, Lint { label: "bare_trait_objects", @@ -39,6 +49,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "break_with_label_and_loop", description: r##"`break` expression with label and unlabeled loop as value expression"##, }, + Lint { + label: "byte_slice_in_packed_struct_with_derive", + description: r##"`[u8]` or `str` used in a packed struct with `derive`"##, + }, Lint { label: "cenum_impl_drop_cast", description: r##"a C-like enum implementing Drop is cast"##, @@ -51,6 +65,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "coherence_leak_check", description: r##"distinct impls distinguished only by the leak-check code"##, }, + Lint { + label: "coinductive_overlap_in_coherence", + description: r##"impls that are not considered to overlap may be considered to overlap in the future"##, + }, Lint { label: "conflicting_repr_hints", description: r##"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice"##, @@ -59,10 +77,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "confusable_idents", description: r##"detects visually confusable pairs between identifiers"##, }, - Lint { - label: "const_err", - description: r##"constant evaluation encountered erroneous expression"##, - }, Lint { label: "const_evaluatable_unchecked", description: r##"detects a generic constant is used in a type without a emitting a warning"##, @@ -71,12 +85,24 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "const_item_mutation", description: r##"detects attempts to mutate a `const` item"##, }, + Lint { + label: "const_patterns_without_partial_eq", + description: r##"constant in pattern does not implement `PartialEq`"##, + }, Lint { label: "dead_code", description: r##"detect unused, unexported items"## }, Lint { label: "deprecated", description: r##"detects use of deprecated items"## }, + Lint { + label: "deprecated_cfg_attr_crate_type_name", + description: r##"detects usage of `#![cfg_attr(..., crate_type/crate_name = "...")]`"##, + }, Lint { label: "deprecated_in_future", description: r##"detects use of items that will be deprecated in a future version"##, }, + Lint { + label: "deprecated_where_clause_location", + description: r##"deprecated where clause location"##, + }, Lint { label: "deref_into_dyn_supertrait", description: r##"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future"##, @@ -89,10 +115,23 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "drop_bounds", description: r##"bounds of the form `T: Drop` are most likely incorrect"##, }, + Lint { + label: "dropping_copy_types", + description: r##"calls to `std::mem::drop` with a value that implements Copy"##, + }, + Lint { + label: "dropping_references", + description: r##"calls to `std::mem::drop` with a reference instead of an owned value"##, + }, + Lint { label: "duplicate_macro_attributes", description: r##"duplicated attribute"## }, Lint { label: "dyn_drop", description: r##"trait objects of the form `dyn Drop` are useless"##, }, + Lint { + label: "elided_lifetimes_in_associated_constant", + description: r##"elided lifetimes cannot be used in associated constants in impls"##, + }, Lint { label: "elided_lifetimes_in_paths", description: r##"hidden lifetime parameters in types are deprecated"##, @@ -113,14 +152,38 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "exported_private_dependencies", description: r##"public interface leaks type from a private dependency"##, }, + Lint { + label: "ffi_unwind_calls", + description: r##"call to foreign functions or function pointers with FFI-unwind ABI"##, + }, + Lint { + label: "for_loops_over_fallibles", + description: r##"for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`"##, + }, Lint { label: "forbidden_lint_groups", description: r##"applying forbid to lint-groups"## }, + Lint { + label: "forgetting_copy_types", + description: r##"calls to `std::mem::forget` with a value that implements Copy"##, + }, + Lint { + label: "forgetting_references", + description: r##"calls to `std::mem::forget` with a reference instead of an owned value"##, + }, Lint { label: "function_item_references", description: r##"suggest casting to a function pointer when attempting to take references to function items"##, }, Lint { label: "future_incompatible", - description: r##"lint group for: forbidden-lint-groups, illegal-floating-point-literal-pattern, private-in-public, pub-use-of-private-extern-crate, invalid-type-param-default, const-err, unaligned-references, patterns-in-fns-without-body, missing-fragment-specifier, late-bound-lifetime-arguments, order-dependent-trait-objects, coherence-leak-check, unstable-name-collisions, where-clauses-object-safety, proc-macro-derive-resolution-fallback, macro-expanded-macro-exports-accessed-by-absolute-paths, ill-formed-attribute-input, conflicting-repr-hints, ambiguous-associated-items, mutable-borrow-reservation-conflict, indirect-structural-match, pointer-structural-match, nontrivial-structural-match, soft-unstable, cenum-impl-drop-cast, const-evaluatable-unchecked, uninhabited-static, unsupported-naked-functions, invalid-doc-attributes, semicolon-in-expressions-from-macros, legacy-derive-helpers, proc-macro-back-compat, unsupported-calling-conventions, deref-into-dyn-supertrait"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-alignment, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, + }, + Lint { + label: "fuzzy_provenance_casts", + description: r##"a fuzzy integer to pointer cast is used"##, + }, + Lint { + label: "hidden_glob_reexports", + description: r##"name introduced by a private item shadows a name introduced by a public glob re-export"##, }, Lint { label: "ill_formed_attribute_input", @@ -130,6 +193,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "illegal_floating_point_literal_pattern", description: r##"floating-point literals cannot be used in patterns"##, }, + Lint { + label: "implied_bounds_entailment", + description: r##"impl method assumes more implied bounds than its corresponding trait method"##, + }, Lint { label: "improper_ctypes", description: r##"proper use of libc types in foreign modules"##, @@ -155,6 +222,14 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "inline_no_sanitize", description: r##"detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`"##, }, + Lint { + label: "internal_features", + description: r##"internal features are not supposed to be used"##, + }, + Lint { + label: "invalid_alignment", + description: r##"raw pointers must be aligned before dereferencing"##, + }, Lint { label: "invalid_atomic_ordering", description: r##"usage of invalid atomic ordering in atomic operations and memory fences"##, @@ -163,6 +238,26 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "invalid_doc_attributes", description: r##"detects invalid `#[doc(...)]` attributes"##, }, + Lint { + label: "invalid_from_utf8", + description: r##"using a non UTF-8 literal in `std::str::from_utf8`"##, + }, + Lint { + label: "invalid_from_utf8_unchecked", + description: r##"using a non UTF-8 literal in `std::str::from_utf8_unchecked`"##, + }, + Lint { + label: "invalid_macro_export_arguments", + description: r##""invalid_parameter" isn't a valid argument for `#[macro_export]`"##, + }, + Lint { + label: "invalid_nan_comparisons", + description: r##"detects invalid floating point NaN comparisons"##, + }, + Lint { + label: "invalid_reference_casting", + description: r##"casts of `&T` to `&mut T` without interior mutability"##, + }, Lint { label: "invalid_type_param_default", description: r##"type parameter default erroneously allowed in invalid location"##, @@ -188,6 +283,26 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "legacy_derive_helpers", description: r##"detects derive helper attributes that are used before they are introduced"##, }, + Lint { + label: "let_underscore", + description: r##"lint group for: let-underscore-drop, let-underscore-lock"##, + }, + Lint { + label: "let_underscore_drop", + description: r##"non-binding let on a type that implements `Drop`"##, + }, + Lint { + label: "let_underscore_lock", + description: r##"non-binding let on a synchronization lock"##, + }, + Lint { + label: "long_running_const_eval", + description: r##"detects long const eval operations"##, + }, + Lint { + label: "lossy_provenance_casts", + description: r##"a lossy pointer to integer cast is used"##, + }, Lint { label: "macro_expanded_macro_exports_accessed_by_absolute_paths", description: r##"macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths"##, @@ -196,6 +311,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "macro_use_extern_crate", description: r##"the `#[macro_use]` attribute is now deprecated in favor of using macros via the module system"##, }, + Lint { + label: "map_unit_fn", + description: r##"`Iterator::map` call that discard the iterator's values"##, + }, Lint { label: "meta_variable_misuse", description: r##"possible meta-variable misuse at macro definition"##, @@ -221,17 +340,21 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "mixed_script_confusables", description: r##"detects Unicode scripts whose mixed script confusables codepoints are solely used"##, }, + Lint { + label: "multiple_supertrait_upcastable", + description: r##"detect when an object-safe trait has multiple supertraits"##, + }, Lint { label: "must_not_suspend", description: r##"use of a `#[must_not_suspend]` value across a yield point"##, }, Lint { - label: "mutable_borrow_reservation_conflict", - description: r##"reservation of a two-phased borrow conflicts with other shared borrows"##, + label: "mutable_transmutes", + description: r##"transmuting &T to &mut T is undefined behavior, even if the reference is unused"##, }, Lint { - label: "mutable_transmutes", - description: r##"mutating transmuted &mut T from &T may cause undefined behavior"##, + label: "named_arguments_used_positionally", + description: r##"named arguments in format used positionally"##, }, Lint { label: "named_asm_labels", description: r##"named labels in inline assembly"## }, Lint { @@ -276,6 +399,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "noop_method_call", description: r##"detects the use of well-known noop methods"##, }, + Lint { + label: "opaque_hidden_inferred_bound", + description: r##"detects the use of nested `impl Trait` types in associated type bounds that are not general enough"##, + }, Lint { label: "order_dependent_trait_objects", description: r##"trait-object types were treated as different depending on marker-trait order"##, @@ -295,8 +422,12 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"pointers are not structural-match"##, }, Lint { - label: "private_in_public", - description: r##"detect private items in public interfaces not caught by the old implementation"##, + label: "private_bounds", + description: r##"private type in secondary interface of an item"##, + }, + Lint { + label: "private_interfaces", + description: r##"private type in primary interface of an item"##, }, Lint { label: "proc_macro_back_compat", @@ -314,13 +445,21 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "redundant_semicolons", description: r##"detects unnecessary trailing semicolons"##, }, + Lint { + label: "refining_impl_trait", + description: r##"impl trait in impl method signature does not match trait method signature"##, + }, Lint { label: "renamed_and_removed_lints", description: r##"lints that have been renamed or removed"##, }, + Lint { + label: "repr_transparent_external_private_fields", + description: r##"transparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields"##, + }, Lint { label: "rust_2018_compatibility", - description: r##"lint group for: keyword-idents, anonymous-parameters, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate"##, + description: r##"lint group for: keyword-idents, anonymous-parameters, absolute-paths-not-starting-with-crate, tyvar-behind-raw-pointer"##, }, Lint { label: "rust_2018_idioms", @@ -328,7 +467,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, Lint { label: "rust_2021_compatibility", - description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prelude-collisions, rust-2021-prefixes-incompatible-syntax, array-into-iter, non-fmt-panics"##, + description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prefixes-incompatible-syntax, rust-2021-prelude-collisions, array-into-iter, non-fmt-panics"##, }, Lint { label: "rust_2021_incompatible_closure_captures", @@ -358,14 +497,30 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "soft_unstable", description: r##"a feature gate that doesn't break dependent crates"##, }, + Lint { + label: "special_module_name", + description: r##"module declarations for files with a special meaning"##, + }, Lint { label: "stable_features", description: r##"stable features found in `#[feature]` directive"##, }, + Lint { + label: "suspicious_auto_trait_impls", + description: r##"the rules governing auto traits have recently changed resulting in potential breakage"##, + }, + Lint { + label: "suspicious_double_ref_op", + description: r##"suspicious call of trait method on `&&T`"##, + }, Lint { label: "temporary_cstring_as_ptr", description: r##"detects getting the inner pointer of a temporary `CString`"##, }, + Lint { + label: "test_unstable_lint", + description: r##"this unstable lint is only for testing"##, + }, Lint { label: "text_direction_codepoint_in_comment", description: r##"invisible directionality-changing codepoints in comment"##, @@ -394,10 +549,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "tyvar_behind_raw_pointer", description: r##"raw pointer to an inference variable"##, }, - Lint { - label: "unaligned_references", - description: r##"detects unaligned references to fields of packed structs"##, - }, Lint { label: "uncommon_codepoints", description: r##"detects uncommon Unicode codepoints in identifiers"##, @@ -410,23 +561,54 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unconditional_recursion", description: r##"functions that cannot return without calling themselves"##, }, + Lint { + label: "undefined_naked_function_abi", + description: r##"undefined naked function ABI"##, + }, + Lint { + label: "undropped_manually_drops", + description: r##"calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of it's inner value"##, + }, + Lint { + label: "unexpected_cfgs", + description: r##"detects unexpected names and values in `#[cfg]` conditions"##, + }, + Lint { + label: "unfulfilled_lint_expectations", + description: r##"unfulfilled lint expectation"##, + }, + Lint { + label: "ungated_async_fn_track_caller", + description: r##"enabling track_caller on an async fn is a no-op unless the async_fn_track_caller feature is enabled"##, + }, Lint { label: "uninhabited_static", description: r##"uninhabited static"## }, Lint { label: "unknown_crate_types", description: r##"unknown crate type found in `#[crate_type]` directive"##, }, Lint { label: "unknown_lints", description: r##"unrecognized lint attribute"## }, + Lint { + label: "unknown_or_malformed_diagnostic_attributes", + description: r##"unrecognized or malformed diagnostic attribute"##, + }, Lint { label: "unnameable_test_items", description: r##"detects an item that cannot be named being marked as `#[test_case]`"##, }, + Lint { + label: "unnameable_types", + description: r##"effective visibility of a type is larger than the area in which it can be named"##, + }, Lint { label: "unreachable_code", description: r##"detects unreachable code paths"## }, Lint { label: "unreachable_patterns", description: r##"detects unreachable patterns"## }, Lint { label: "unreachable_pub", description: r##"`pub` items not reachable from crate root"##, }, - Lint { label: "unsafe_code", description: r##"usage of `unsafe` code"## }, + Lint { + label: "unsafe_code", + description: r##"usage of `unsafe` code and other potentially unsound constructs"##, + }, Lint { label: "unsafe_op_in_unsafe_fn", description: r##"unsafe operations in unsafe functions without an explicit unsafe block are deprecated"##, @@ -439,17 +621,17 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unstable_name_collisions", description: r##"detects name collision with an existing but unstable method"##, }, + Lint { + label: "unstable_syntax_pre_expansion", + description: r##"unstable syntax can change at any point in the future, causing a hard error!"##, + }, Lint { label: "unsupported_calling_conventions", description: r##"use of unsupported calling convention"##, }, - Lint { - label: "unsupported_naked_functions", - description: r##"unsupported naked function definitions"##, - }, Lint { label: "unused", - description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons"##, + description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn"##, }, Lint { label: "unused_allocation", @@ -459,6 +641,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unused_assignments", description: r##"detect assignments that will never be read"##, }, + Lint { + label: "unused_associated_type_bounds", + description: r##"detects unused `Foo = Bar` bounds in `dyn Trait`"##, + }, Lint { label: "unused_attributes", description: r##"detects attributes that were not used by the compiler"##, @@ -491,6 +677,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unused_lifetimes", description: r##"detects lifetime parameters that are never used"##, }, + Lint { + label: "unused_macro_rules", + description: r##"detects macro rules that were not used"##, + }, Lint { label: "unused_macros", description: r##"detects macros that were not used"## }, Lint { label: "unused_must_use", @@ -512,6 +702,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "unused_results", description: r##"unused result of an expression in a statement"##, }, + Lint { + label: "unused_tuple_struct_fields", + description: r##"detects tuple struct fields that are never read"##, + }, Lint { label: "unused_unsafe", description: r##"unnecessary use of an `unsafe` block"## }, Lint { label: "unused_variables", @@ -521,6 +715,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "useless_deprecated", description: r##"detects deprecation attributes with no effect"##, }, + Lint { + label: "useless_ptr_null_checks", + description: r##"useless checking of non-null-typed pointer"##, + }, Lint { label: "variant_size_differences", description: r##"detects enums with widely varying variant sizes"##, @@ -542,49 +740,63 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"suggest using `loop { }` instead of `while true { }`"##, }, ]; + pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "future_incompatible", - description: r##"lint group for: forbidden-lint-groups, illegal-floating-point-literal-pattern, private-in-public, pub-use-of-private-extern-crate, invalid-type-param-default, const-err, unaligned-references, patterns-in-fns-without-body, missing-fragment-specifier, late-bound-lifetime-arguments, order-dependent-trait-objects, coherence-leak-check, unstable-name-collisions, where-clauses-object-safety, proc-macro-derive-resolution-fallback, macro-expanded-macro-exports-accessed-by-absolute-paths, ill-formed-attribute-input, conflicting-repr-hints, ambiguous-associated-items, mutable-borrow-reservation-conflict, indirect-structural-match, pointer-structural-match, nontrivial-structural-match, soft-unstable, cenum-impl-drop-cast, const-evaluatable-unchecked, uninhabited-static, unsupported-naked-functions, invalid-doc-attributes, semicolon-in-expressions-from-macros, legacy-derive-helpers, proc-macro-back-compat, unsupported-calling-conventions, deref-into-dyn-supertrait"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-alignment, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, }, children: &[ - "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", + "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", ], }, + LintGroup { + lint: Lint { + label: "let_underscore", + description: r##"lint group for: let-underscore-drop, let-underscore-lock"##, + }, + children: &["let_underscore_drop", "let_underscore_lock"], + }, LintGroup { lint: Lint { label: "nonstandard_style", @@ -595,13 +807,13 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "rust_2018_compatibility", - description: r##"lint group for: keyword-idents, anonymous-parameters, tyvar-behind-raw-pointer, absolute-paths-not-starting-with-crate"##, + description: r##"lint group for: keyword-idents, anonymous-parameters, absolute-paths-not-starting-with-crate, tyvar-behind-raw-pointer"##, }, children: &[ "keyword_idents", "anonymous_parameters", - "tyvar_behind_raw_pointer", "absolute_paths_not_starting_with_crate", + "tyvar_behind_raw_pointer", ], }, LintGroup { @@ -620,15 +832,15 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "rust_2021_compatibility", - description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prelude-collisions, rust-2021-prefixes-incompatible-syntax, array-into-iter, non-fmt-panics"##, + description: r##"lint group for: ellipsis-inclusive-range-patterns, bare-trait-objects, rust-2021-incompatible-closure-captures, rust-2021-incompatible-or-patterns, rust-2021-prefixes-incompatible-syntax, rust-2021-prelude-collisions, array-into-iter, non-fmt-panics"##, }, children: &[ "ellipsis_inclusive_range_patterns", "bare_trait_objects", "rust_2021_incompatible_closure_captures", "rust_2021_incompatible_or_patterns", - "rust_2021_prelude_collisions", "rust_2021_prefixes_incompatible_syntax", + "rust_2021_prelude_collisions", "array_into_iter", "non_fmt_panics", ], @@ -636,7 +848,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "unused", - description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons"##, + description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn"##, }, children: &[ "unused_imports", @@ -651,6 +863,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "path_statements", "unused_attributes", "unused_macros", + "unused_macro_rules", "unused_allocation", "unused_doc_comments", "unused_extern_crates", @@ -659,6 +872,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "unused_parens", "unused_braces", "redundant_semicolons", + "map_unit_fn", ], }, LintGroup { @@ -673,7 +887,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ pub const RUSTDOC_LINTS: &[Lint] = &[ Lint { label: "rustdoc::all", - description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::missing-doc-code-examples, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs"##, + description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links"##, }, Lint { label: "rustdoc::bare_urls", description: r##"detects URLs that are not hyperlinks"## }, Lint { @@ -708,26 +922,69 @@ pub const RUSTDOC_LINTS: &[Lint] = &[ label: "rustdoc::private_intra_doc_links", description: r##"linking from a public item to a private one"##, }, + Lint { + label: "rustdoc::redundant_explicit_links", + description: r##"detects redundant explicit links in doc comments"##, + }, + Lint { + label: "rustdoc::unescaped_backticks", + description: r##"detects unescaped backticks in doc comments"##, + }, ]; + pub const RUSTDOC_LINT_GROUPS: &[LintGroup] = &[LintGroup { lint: Lint { label: "rustdoc::all", - description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::missing-doc-code-examples, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs"##, + description: r##"lint group for: rustdoc::broken-intra-doc-links, rustdoc::private-intra-doc-links, rustdoc::private-doc-tests, rustdoc::invalid-codeblock-attributes, rustdoc::invalid-rust-codeblocks, rustdoc::invalid-html-tags, rustdoc::bare-urls, rustdoc::missing-crate-level-docs, rustdoc::unescaped-backticks, rustdoc::redundant-explicit-links"##, }, children: &[ "rustdoc::broken_intra_doc_links", "rustdoc::private_intra_doc_links", - "rustdoc::missing_doc_code_examples", "rustdoc::private_doc_tests", "rustdoc::invalid_codeblock_attributes", "rustdoc::invalid_rust_codeblocks", "rustdoc::invalid_html_tags", "rustdoc::bare_urls", "rustdoc::missing_crate_level_docs", + "rustdoc::unescaped_backticks", + "rustdoc::redundant_explicit_links", ], }]; pub const FEATURES: &[Lint] = &[ + Lint { + label: "aarch64_ver_target_feature", + description: r##"# `aarch64_ver_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "abi_amdgpu_kernel", + description: r##"# `abi_amdgpu_kernel` + +The tracking issue for this feature is: [#51575] + +[#51575]: https://github.com/rust-lang/rust/issues/51575 + +------------------------ +"##, + }, + Lint { + label: "abi_avr_interrupt", + description: r##"# `abi_avr_interrupt` + +The tracking issue for this feature is: [#69664] + +[#69664]: https://github.com/rust-lang/rust/issues/69664 + +------------------------ +"##, + }, Lint { label: "abi_c_cmse_nonsecure_call", description: r##"# `abi_c_cmse_nonsecure_call` @@ -928,6 +1185,121 @@ $ cat $(find -name '*.s') ret; } ``` +"##, + }, + 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 { @@ -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] - -[#60553]: https://github.com/rust-lang/rust/issues/60553 +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. ------------------------ +"##, + }, + Lint { + label: "allow_internal_unstable", + description: r##"# `allow_internal_unstable` -The `arbitrary_enum_discriminant` feature permits tuple-like and -struct-like enum variants with `#[repr()]` 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: "anonymous_lifetime_in_impl_trait", + description: r##"# `anonymous_lifetime_in_impl_trait` -```rust -#![feature(arbitrary_enum_discriminant)] +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. -#[allow(dead_code)] -#[repr(u8)] -enum Enum { - Unit = 3, - Tuple(u16) = 2, - Struct { - a: u8, - b: u16, - } = 1, -} +------------------------ +"##, + }, + Lint { + label: "arbitrary_self_types", + description: r##"# `arbitrary_self_types` -impl Enum { - fn tag(&self) -> u8 { - unsafe { *(self as *const Self as *const u8) } - } -} +The tracking issue for this feature is: [#44874] -assert_eq!(3, Enum::Unit.tag()); -assert_eq!(2, Enum::Tuple(5).tag()); -assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag()); -``` +[#44874]: https://github.com/rust-lang/rust/issues/44874 + +------------------------ +"##, + }, + Lint { + label: "arc_unwrap_or_clone", + description: r##"# `arc_unwrap_or_clone` + +The tracking issue for this feature is: [#93610] + +[#93610]: https://github.com/rust-lang/rust/issues/93610 + +------------------------ +"##, + }, + Lint { + label: "arm_target_feature", + description: r##"# `arm_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "array_chunks", + description: r##"# `array_chunks` + +The tracking issue for this feature is: [#74985] + +[#74985]: https://github.com/rust-lang/rust/issues/74985 + +------------------------ +"##, + }, + Lint { + label: "array_into_iter_constructors", + description: r##"# `array_into_iter_constructors` + +The tracking issue for this feature is: [#91583] + +[#91583]: https://github.com/rust-lang/rust/issues/91583 + +------------------------ +"##, + }, + Lint { + label: "array_methods", + description: r##"# `array_methods` + +The tracking issue for this feature is: [#76118] + +[#76118]: https://github.com/rust-lang/rust/issues/76118 + +------------------------ +"##, + }, + Lint { + label: "array_try_from_fn", + description: r##"# `array_try_from_fn` + +The tracking issue for this feature is: [#89379] + +[#89379]: https://github.com/rust-lang/rust/issues/89379 + +------------------------ +"##, + }, + Lint { + label: "array_try_map", + description: r##"# `array_try_map` + +The tracking issue for this feature is: [#79711] + +[#79711]: https://github.com/rust-lang/rust/issues/79711 + +------------------------ +"##, + }, + Lint { + label: "array_windows", + description: r##"# `array_windows` + +The tracking issue for this feature is: [#75027] + +[#75027]: https://github.com/rust-lang/rust/issues/75027 + +------------------------ +"##, + }, + Lint { + label: "as_array_of_cells", + description: r##"# `as_array_of_cells` + +The tracking issue for this feature is: [#88248] + +[#88248]: https://github.com/rust-lang/rust/issues/88248 + +------------------------ +"##, + }, + Lint { + label: "ascii_char", + description: r##"# `ascii_char` + +The tracking issue for this feature is: [#110998] + +[#110998]: https://github.com/rust-lang/rust/issues/110998 + +------------------------ +"##, + }, + Lint { + label: "ascii_char_variants", + description: r##"# `ascii_char_variants` + +The tracking issue for this feature is: [#110998] + +[#110998]: https://github.com/rust-lang/rust/issues/110998 + +------------------------ "##, }, Lint { label: "asm_const", description: r##"# `asm_const` -The tracking issue for this feature is: [#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 ` 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`. -"##, - }, - Lint { - label: "asm_sym", - description: r##"# `asm_sym` - -The tracking issue for this feature is: [#72016] - -[#72016]: https://github.com/rust-lang/rust/issues/72016 - ------------------------- - -This feature adds a `sym ` operand type to `asm!` and `global_asm!`. -- `` must refer to a `fn` or `static`. -- A mangled symbol name referring to the item is substituted into the asm template string. -- The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc). -- `` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data. +- MSP430 + - The status register `r2`. +- M68k + - The condition code register `ccr`. +- s390x + - The condition code register `cc`. "##, }, Lint { 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 `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: "assert_matches", + description: r##"# `assert_matches` + +The tracking issue for this feature is: [#82775] + +[#82775]: https://github.com/rust-lang/rust/issues/82775 + +------------------------ +"##, + }, + Lint { + label: "associated_const_equality", + description: r##"# `associated_const_equality` + +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 {} @@ -1275,6 +1941,116 @@ Auto traits cannot have any trait items, such as methods or associated types. Th ## Supertraits Auto traits cannot have supertraits. This is for soundness reasons, as the interaction of coinduction with implied bounds is difficult to reconcile. +"##, + }, + Lint { + label: "avx512_target_feature", + description: r##"# `avx512_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "backtrace_frames", + description: r##"# `backtrace_frames` + +The tracking issue for this feature is: [#79676] + +[#79676]: https://github.com/rust-lang/rust/issues/79676 + +------------------------ +"##, + }, + Lint { + label: "bigint_helper_methods", + description: r##"# `bigint_helper_methods` + +The tracking issue for this feature is: [#85532] + +[#85532]: https://github.com/rust-lang/rust/issues/85532 + +------------------------ +"##, + }, + Lint { + label: "binary_heap_as_slice", + description: r##"# `binary_heap_as_slice` + +The tracking issue for this feature is: [#83659] + +[#83659]: https://github.com/rust-lang/rust/issues/83659 + +------------------------ +"##, + }, + Lint { + label: "binary_heap_drain_sorted", + description: r##"# `binary_heap_drain_sorted` + +The tracking issue for this feature is: [#59278] + +[#59278]: https://github.com/rust-lang/rust/issues/59278 + +------------------------ +"##, + }, + Lint { + label: "binary_heap_into_iter_sorted", + description: r##"# `binary_heap_into_iter_sorted` + +The tracking issue for this feature is: [#59278] + +[#59278]: https://github.com/rust-lang/rust/issues/59278 + +------------------------ +"##, + }, + Lint { + label: "bound_as_ref", + description: r##"# `bound_as_ref` + +The tracking issue for this feature is: [#80996] + +[#80996]: https://github.com/rust-lang/rust/issues/80996 + +------------------------ +"##, + }, + Lint { + label: "bound_map", + description: r##"# `bound_map` + +The tracking issue for this feature is: [#86026] + +[#86026]: https://github.com/rust-lang/rust/issues/86026 + +------------------------ +"##, + }, + Lint { + label: "box_into_boxed_slice", + description: r##"# `box_into_boxed_slice` + +The tracking issue for this feature is: [#71582] + +[#71582]: https://github.com/rust-lang/rust/issues/71582 + +------------------------ +"##, + }, + Lint { + label: "box_into_inner", + description: r##"# `box_into_inner` + +The tracking issue for this feature is: [#80437] + +[#80437]: https://github.com/rust-lang/rust/issues/80437 + +------------------------ "##, }, Lint { @@ -1285,8 +2061,6 @@ The tracking issue for this feature is: [#29641] [#29641]: https://github.com/rust-lang/rust/issues/29641 -See also [`box_syntax`](box-syntax.md) - ------------------------ Box patterns let you match on `Box`s: @@ -1299,10 +2073,10 @@ fn main() { let b = Some(Box::new(5)); match b { Some(box n) if n < 0 => { - println!("Box contains negative number {}", n); + println!("Box contains negative number {n}"); }, Some(box n) if n >= 0 => { - println!("Box contains non-negative number {}", n); + println!("Box contains non-negative number {n}"); }, None => { println!("No box"); @@ -1314,29 +2088,102 @@ fn main() { "##, }, Lint { - label: "box_syntax", - description: r##"# `box_syntax` + label: "bpf_target_feature", + description: r##"# `bpf_target_feature` -The tracking issue for this feature is: [#49733] +The tracking issue for this feature is: [#44839] -[#49733]: https://github.com/rust-lang/rust/issues/49733 - -See also [`box_patterns`](box-patterns.md) +[#44839]: https://github.com/rust-lang/rust/issues/44839 ------------------------ +"##, + }, + Lint { + label: "btree_cursors", + description: r##"# `btree_cursors` -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: [#107540] -```rust -#![feature(box_syntax)] +[#107540]: https://github.com/rust-lang/rust/issues/107540 -fn main() { - let b = box 5; -} -``` +------------------------ +"##, + }, + Lint { + label: "btree_extract_if", + description: r##"# `btree_extract_if` + +The tracking issue for this feature is: [#70530] + +[#70530]: https://github.com/rust-lang/rust/issues/70530 + +------------------------ +"##, + }, + 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 { @@ -1503,6 +2407,61 @@ fn b() { } } ``` +"##, + }, + Lint { + label: "cfg_target_abi", + description: r##"# `cfg_target_abi` + +The tracking issue for this feature is: [#80970] + +[#80970]: https://github.com/rust-lang/rust/issues/80970 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_compact", + description: r##"# `cfg_target_compact` + +The tracking issue for this feature is: [#96901] + +[#96901]: https://github.com/rust-lang/rust/issues/96901 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_has_atomic", + description: r##"# `cfg_target_has_atomic` + +The tracking issue for this feature is: [#94039] + +[#94039]: https://github.com/rust-lang/rust/issues/94039 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_has_atomic_equal_alignment", + description: r##"# `cfg_target_has_atomic_equal_alignment` + +The tracking issue for this feature is: [#93822] + +[#93822]: https://github.com/rust-lang/rust/issues/93822 + +------------------------ +"##, + }, + Lint { + label: "cfg_target_thread_local", + description: r##"# `cfg_target_thread_local` + +The tracking issue for this feature is: [#29594] + +[#29594]: https://github.com/rust-lang/rust/issues/29594 + +------------------------ "##, }, Lint { @@ -1545,10 +2504,72 @@ fn b() { "##, }, Lint { - label: "char_error_internals", - description: r##"# `char_error_internals` + label: "cfi_encoding", + description: r##"# `cfi_encoding` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#89653] + +[#89653]: https://github.com/rust-lang/rust/issues/89653 + +------------------------ + +The `cfi_encoding` feature allows the user to define a CFI encoding for a type. +It allows the user to use a different names for types that otherwise would be +required to have the same name as used in externally defined C functions. + +## Examples + +```rust +#![feature(cfi_encoding, extern_types)] + +#[cfi_encoding = "3Foo"] +pub struct Type1(i32); + +extern { + #[cfi_encoding = "3Bar"] + type Type2; +} +``` +"##, + }, + Lint { + label: "char_indices_offset", + description: r##"# `char_indices_offset` + +The tracking issue for this feature is: [#83871] + +[#83871]: https://github.com/rust-lang/rust/issues/83871 + +------------------------ +"##, + }, + Lint { + label: "char_internals", + description: r##"# `char_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "char_min", + description: r##"# `char_min` + +The tracking issue for this feature is: [#114298] + +[#114298]: https://github.com/rust-lang/rust/issues/114298 + +------------------------ +"##, + }, + Lint { + label: "closure_lifetime_binder", + description: r##"# `closure_lifetime_binder` + +The tracking issue for this feature is: [#97362] + +[#97362]: https://github.com/rust-lang/rust/issues/97362 ------------------------ "##, @@ -1567,6 +2588,17 @@ Allows using the `#[track_caller]` attribute on closures and generators. Calls made to the closure or generator will have caller information available through `std::panic::Location::caller()`, just like using `#[track_caller]` on a function. +"##, + }, + Lint { + label: "cmp_minmax", + description: r##"# `cmp_minmax` + +The tracking issue for this feature is: [#115939] + +[#115939]: https://github.com/rust-lang/rust/issues/115939 + +------------------------ "##, }, Lint { @@ -1652,6 +2684,28 @@ $ arm-none-eabi-objdump -D function.o 3c: f7ff fffe bl 0 <_ZN4core9panicking5panic17h5c028258ca2fb3f5E> 40: defe udf #254 ; 0xfe ``` +"##, + }, + Lint { + label: "coerce_unsized", + description: r##"# `coerce_unsized` + +The tracking issue for this feature is: [#18598] + +[#18598]: https://github.com/rust-lang/rust/issues/18598 + +------------------------ +"##, + }, + Lint { + label: "collapse_debuginfo", + description: r##"# `collapse_debuginfo` + +The tracking issue for this feature is: [#100758] + +[#100758]: https://github.com/rust-lang/rust/issues/100758 + +------------------------ "##, }, Lint { @@ -1660,6 +2714,17 @@ $ arm-none-eabi-objdump -D function.o This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "concat_bytes", + description: r##"# `concat_bytes` + +The tracking issue for this feature is: [#87555] + +[#87555]: https://github.com/rust-lang/rust/issues/87555 + ------------------------ "##, }, @@ -1690,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: [#67217] +The tracking issue for this feature is: [#46571] -[#67217]: https://github.com/rust-lang/rust/issues/67217 +[#46571]: https://github.com/rust-lang/rust/issues/46571 -The `const_eval_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`. +------------------------ +"##, + }, + Lint { + label: "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: [#57349] + +[#57349]: https://github.com/rust-lang/rust/issues/57349 + +------------------------ +"##, + }, + 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,27 +3815,112 @@ 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 { @@ -1794,6 +3957,17 @@ const WILL_PASS: i32 = 0; #[test_case] const WILL_FAIL: i32 = 4; ``` +"##, + }, + Lint { + label: "deadline_api", + description: r##"# `deadline_api` + +The tracking issue for this feature is: [#46316] + +[#46316]: https://github.com/rust-lang/rust/issues/46316 + +------------------------ "##, }, Lint { @@ -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 { @@ -1862,6 +4029,15 @@ fn main() { This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "derive_const", + description: r##"# `derive_const` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -1871,6 +4047,79 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "diagnostic_namespace", + description: r##"# `diagnostic_namespace` + +The tracking issue for this feature is: [#111996] + +[#111996]: https://github.com/rust-lang/rust/issues/111996 + +------------------------ +"##, + }, + Lint { + label: "dir_entry_ext2", + description: r##"# `dir_entry_ext2` + +The tracking issue for this feature is: [#85573] + +[#85573]: https://github.com/rust-lang/rust/issues/85573 + +------------------------ +"##, + }, + Lint { + label: "discriminant_kind", + description: r##"# `discriminant_kind` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "dispatch_from_dyn", + description: r##"# `dispatch_from_dyn` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "div_duration", + description: r##"# `div_duration` + +The tracking issue for this feature is: [#63139] + +[#63139]: https://github.com/rust-lang/rust/issues/63139 + +------------------------ +"##, + }, + Lint { + label: "do_not_recommend", + description: r##"# `do_not_recommend` + +The tracking issue for this feature is: [#51992] + +[#51992]: https://github.com/rust-lang/rust/issues/51992 + +------------------------ +"##, + }, + Lint { + label: "doc_auto_cfg", + description: r##"# `doc_auto_cfg` + +The tracking issue for this feature is: [#43781] + +[#43781]: https://github.com/rust-lang/rust/issues/43781 + ------------------------ "##, }, @@ -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. @@ -1922,6 +4171,17 @@ pub struct Icon { [#43781]: https://github.com/rust-lang/rust/issues/43781 [#43348]: https://github.com/rust-lang/rust/issues/43348 +"##, + }, + Lint { + label: "doc_cfg_hide", + description: r##"# `doc_cfg_hide` + +The tracking issue for this feature is: [#43781] + +[#43781]: https://github.com/rust-lang/rust/issues/43781 + +------------------------ "##, }, Lint { @@ -1987,6 +4247,180 @@ See also its documentation in [the rustdoc book][rustdoc-book-notable_trait]. [#45040]: https://github.com/rust-lang/rust/issues/45040 [#45039]: https://github.com/rust-lang/rust/pull/45039 [rustdoc-book-notable_trait]: ../../rustdoc/unstable-features.html#adding-your-trait-to-the-notable-traits-dialog +"##, + }, + Lint { + label: "downcast_unchecked", + description: r##"# `downcast_unchecked` + +The tracking issue for this feature is: [#90850] + +[#90850]: https://github.com/rust-lang/rust/issues/90850 + +------------------------ +"##, + }, + Lint { + label: "drain_keep_rest", + description: r##"# `drain_keep_rest` + +The tracking issue for this feature is: [#101122] + +[#101122]: https://github.com/rust-lang/rust/issues/101122 + +------------------------ +"##, + }, + Lint { + label: "dropck_eyepatch", + description: r##"# `dropck_eyepatch` + +The tracking issue for this feature is: [#34761] + +[#34761]: https://github.com/rust-lang/rust/issues/34761 + +------------------------ +"##, + }, + Lint { + label: "duration_constants", + description: r##"# `duration_constants` + +The tracking issue for this feature is: [#57391] + +[#57391]: https://github.com/rust-lang/rust/issues/57391 + +------------------------ +"##, + }, + Lint { + label: "duration_consts_float", + description: r##"# `duration_consts_float` + +The tracking issue for this feature is: [#72440] + +[#72440]: https://github.com/rust-lang/rust/issues/72440 + +------------------------ +"##, + }, + Lint { + label: "dyn_star", + description: r##"# `dyn_star` + +The tracking issue for this feature is: [#102425] + +[#102425]: https://github.com/rust-lang/rust/issues/102425 + +------------------------ +"##, + }, + Lint { + label: "edition_panic", + description: r##"# `edition_panic` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "effects", + description: r##"# `effects` + +The tracking issue for this feature is: [#102090] + +[#102090]: https://github.com/rust-lang/rust/issues/102090 + +------------------------ +"##, + }, + Lint { + label: "entry_insert", + description: r##"# `entry_insert` + +The tracking issue for this feature is: [#65225] + +[#65225]: https://github.com/rust-lang/rust/issues/65225 + +------------------------ +"##, + }, + Lint { + label: "ermsb_target_feature", + description: r##"# `ermsb_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "error_generic_member_access", + description: r##"# `error_generic_member_access` + +The tracking issue for this feature is: [#99301] + +[#99301]: https://github.com/rust-lang/rust/issues/99301 + +------------------------ +"##, + }, + Lint { + label: "error_in_core", + description: r##"# `error_in_core` + +The tracking issue for this feature is: [#103765] + +[#103765]: https://github.com/rust-lang/rust/issues/103765 + +------------------------ +"##, + }, + Lint { + label: "error_iter", + description: r##"# `error_iter` + +The tracking issue for this feature is: [#58520] + +[#58520]: https://github.com/rust-lang/rust/issues/58520 + +------------------------ +"##, + }, + Lint { + label: "error_reporter", + description: r##"# `error_reporter` + +The tracking issue for this feature is: [#90172] + +[#90172]: https://github.com/rust-lang/rust/issues/90172 + +------------------------ +"##, + }, + Lint { + label: "error_type_id", + description: r##"# `error_type_id` + +The tracking issue for this feature is: [#60784] + +[#60784]: https://github.com/rust-lang/rust/issues/60784 + +------------------------ +"##, + }, + Lint { + label: "exact_size_is_empty", + description: r##"# `exact_size_is_empty` + +The tracking issue for this feature is: [#35428] + +[#35428]: https://github.com/rust-lang/rust/issues/35428 + +------------------------ "##, }, Lint { @@ -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 tracking issue for this feature is: [#51085] + +[#51085]: https://github.com/rust-lang/rust/issues/51085 + +------------------------ +"##, + }, + Lint { + label: "exit_status_error", + description: r##"# `exit_status_error` + +The tracking issue for this feature is: [#84908] + +[#84908]: https://github.com/rust-lang/rust/issues/84908 + +------------------------ +"##, + }, + Lint { + label: "exitcode_exit_method", + description: r##"# `exitcode_exit_method` + +The tracking issue for this feature is: [#97100] + +[#97100]: https://github.com/rust-lang/rust/issues/97100 + +------------------------ +"##, + }, + Lint { + label: "explicit_tail_calls", + description: r##"# `explicit_tail_calls` + +The tracking issue for this feature is: [#112788] + +[#112788]: https://github.com/rust-lang/rust/issues/112788 + +------------------------ +"##, + }, + Lint { + label: "extend_one", + description: r##"# `extend_one` + +The tracking issue for this feature is: [#72631] + +[#72631]: https://github.com/rust-lang/rust/issues/72631 + +------------------------ +"##, + }, + Lint { + label: "extended_varargs_abi_support", + description: r##"# `extended_varargs_abi_support` + +The tracking issue for this feature is: [#100189] + +[#100189]: https://github.com/rust-lang/rust/issues/100189 ------------------------ -The `explicit_generic_args_with_impl_trait` feature gate lets you specify generic arguments even -when `impl Trait` is used in argument position. +This feature adds the possibility of using `sysv64`, `win64` or `efiapi` calling +conventions on functions with varargs. +"##, + }, + Lint { + label: "extern_types", + description: r##"# `extern_types` -A simple example is: +The tracking issue for this feature is: [#43467] -```rust -#![feature(explicit_generic_args_with_impl_trait)] +[#43467]: https://github.com/rust-lang/rust/issues/43467 -fn foo(_f: impl AsRef) {} +------------------------ +"##, + }, + Lint { + label: "extract_if", + description: r##"# `extract_if` -fn main() { - foo::("".to_string()); -} -``` +The tracking issue for this feature is: [#43244] -This is currently rejected: +[#43244]: https://github.com/rust-lang/rust/issues/43244 -```text -error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position - --> src/main.rs:6:11 - | -6 | foo::("".to_string()); - | ^^^ explicit generic argument not allowed - -``` - -However it would compile if `explicit_generic_args_with_impl_trait` is enabled. - -Note that the synthetic type parameters from `impl Trait` are still implicit and you -cannot explicitly specify these: - -```rust,compile_fail -#![feature(explicit_generic_args_with_impl_trait)] - -fn foo(_f: impl AsRef) {} -fn bar>(_f: F) {} - -fn main() { - bar::("".to_string()); // Okay - bar::("".to_string()); // Okay - - foo::("".to_string()); // Okay - foo::("".to_string()); // Error, you cannot specify `impl Trait` explicitly -} -``` +------------------------ "##, }, Lint { @@ -2208,6 +4687,72 @@ against are compatible with those of the `#[ffi_pure]`. [ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacigdac.html [GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute [IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_pure.htm +"##, + }, + Lint { + label: "ffi_returns_twice", + description: r##"# `ffi_returns_twice` + +The tracking issue for this feature is: [#58314] + +[#58314]: https://github.com/rust-lang/rust/issues/58314 + +------------------------ +"##, + }, + Lint { + label: "file_create_new", + description: r##"# `file_create_new` + +The tracking issue for this feature is: [#105135] + +[#105135]: https://github.com/rust-lang/rust/issues/105135 + +------------------------ +"##, + }, + Lint { + label: "file_set_times", + description: r##"# `file_set_times` + +The tracking issue for this feature is: [#98245] + +[#98245]: https://github.com/rust-lang/rust/issues/98245 + +------------------------ +"##, + }, + Lint { + label: "float_gamma", + description: r##"# `float_gamma` + +The tracking issue for this feature is: [#99842] + +[#99842]: https://github.com/rust-lang/rust/issues/99842 + +------------------------ +"##, + }, + Lint { + label: "float_minimum_maximum", + description: r##"# `float_minimum_maximum` + +The tracking issue for this feature is: [#91079] + +[#91079]: https://github.com/rust-lang/rust/issues/91079 + +------------------------ +"##, + }, + Lint { + label: "float_next_up_down", + description: r##"# `float_next_up_down` + +The tracking issue for this feature is: [#91399] + +[#91399]: https://github.com/rust-lang/rust/issues/91399 + +------------------------ "##, }, Lint { @@ -2216,6 +4761,15 @@ against are compatible with those of the `#[ffi_pure]`. This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "fmt_helpers_for_derive", + description: r##"# `fmt_helpers_for_derive` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -2225,6 +4779,26 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "fn_align", + description: r##"# `fn_align` + +The tracking issue for this feature is: [#82232] + +[#82232]: https://github.com/rust-lang/rust/issues/82232 + +------------------------ +"##, + }, + Lint { + label: "fn_ptr_trait", + description: r##"# `fn_ptr_trait` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -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)] @@ -2265,6 +4839,90 @@ fn main() { assert_eq!(adder(2), 5); } ``` +"##, + }, + Lint { + label: "forget_unsized", + description: r##"# `forget_unsized` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "format_args_nl", + description: r##"# `format_args_nl` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "fs_try_exists", + description: r##"# `fs_try_exists` + +The tracking issue for this feature is: [#83186] + +[#83186]: https://github.com/rust-lang/rust/issues/83186 + +------------------------ +"##, + }, + Lint { + label: "fundamental", + description: r##"# `fundamental` + +The tracking issue for this feature is: [#29635] + +[#29635]: https://github.com/rust-lang/rust/issues/29635 + +------------------------ +"##, + }, + Lint { + label: "future_join", + description: r##"# `future_join` + +The tracking issue for this feature is: [#91642] + +[#91642]: https://github.com/rust-lang/rust/issues/91642 + +------------------------ +"##, + }, + Lint { + label: "gen_future", + description: r##"# `gen_future` + +The tracking issue for this feature is: [#50547] + +[#50547]: https://github.com/rust-lang/rust/issues/50547 + +------------------------ +"##, + }, + Lint { + label: "generator_clone", + description: r##"# `generator_clone` + +The tracking issue for this feature is: [#95360] + +[#95360]: https://github.com/rust-lang/rust/issues/95360 + +------------------------ +"##, + }, + Lint { + label: "generator_trait", + description: r##"# `generator_trait` + +The tracking issue for this feature is: [#43122] + +[#43122]: https://github.com/rust-lang/rust/issues/43122 + +------------------------ "##, }, Lint { @@ -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 where U: 'static { // <-- currently required - bar: Bar -} -struct Bar { - 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 { - bar: Bar -} -struct Bar { - 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,16 +5578,103 @@ via a declaration like ```rust #![feature(intrinsics)] +#![allow(internal_features)] # fn main() {} extern "rust-intrinsic" { fn transmute(x: T) -> U; - fn offset(dst: *const T, offset: isize) -> *const T; + fn arith_offset(dst: *const T, offset: isize) -> *const T; } ``` As with any other FFI functions, these are always `unsafe` to call. +"##, + }, + Lint { + label: "io_error_downcast", + description: r##"# `io_error_downcast` + +The tracking issue for this feature is: [#99262] + +[#99262]: https://github.com/rust-lang/rust/issues/99262 + +------------------------ +"##, + }, + Lint { + label: "io_error_more", + description: r##"# `io_error_more` + +The tracking issue for this feature is: [#86442] + +[#86442]: https://github.com/rust-lang/rust/issues/86442 + +------------------------ +"##, + }, + Lint { + label: "io_error_uncategorized", + description: r##"# `io_error_uncategorized` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "io_slice_advance", + description: r##"# `io_slice_advance` + +The tracking issue for this feature is: [#62726] + +[#62726]: https://github.com/rust-lang/rust/issues/62726 + +------------------------ +"##, + }, + Lint { + label: "ip", + description: r##"# `ip` + +The tracking issue for this feature is: [#27709] + +[#27709]: https://github.com/rust-lang/rust/issues/27709 + +------------------------ +"##, + }, + Lint { + label: "ip_bits", + description: r##"# `ip_bits` + +The tracking issue for this feature is: [#113744] + +[#113744]: https://github.com/rust-lang/rust/issues/113744 + +------------------------ +"##, + }, + Lint { + label: "ip_in_core", + description: r##"# `ip_in_core` + +The tracking issue for this feature is: [#108443] + +[#108443]: https://github.com/rust-lang/rust/issues/108443 + +------------------------ +"##, + }, + Lint { + label: "is_ascii_octdigit", + description: r##"# `is_ascii_octdigit` + +The tracking issue for this feature is: [#101288] + +[#101288]: https://github.com/rust-lang/rust/issues/101288 + +------------------------ "##, }, Lint { @@ -2743,6 +5690,160 @@ The tracking issue for this feature is: [#53485] Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`; add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `Iterator`. +"##, + }, + Lint { + label: "isqrt", + description: r##"# `isqrt` + +The tracking issue for this feature is: [#116226] + +[#116226]: https://github.com/rust-lang/rust/issues/116226 + +------------------------ +"##, + }, + Lint { + label: "iter_advance_by", + description: r##"# `iter_advance_by` + +The tracking issue for this feature is: [#77404] + +[#77404]: https://github.com/rust-lang/rust/issues/77404 + +------------------------ +"##, + }, + Lint { + label: "iter_array_chunks", + description: r##"# `iter_array_chunks` + +The tracking issue for this feature is: [#100450] + +[#100450]: https://github.com/rust-lang/rust/issues/100450 + +------------------------ +"##, + }, + Lint { + label: "iter_collect_into", + description: r##"# `iter_collect_into` + +The tracking issue for this feature is: [#94780] + +[#94780]: https://github.com/rust-lang/rust/issues/94780 + +------------------------ +"##, + }, + Lint { + label: "iter_from_generator", + description: r##"# `iter_from_generator` + +The tracking issue for this feature is: [#43122] + +[#43122]: https://github.com/rust-lang/rust/issues/43122 + +------------------------ +"##, + }, + Lint { + label: "iter_intersperse", + description: r##"# `iter_intersperse` + +The tracking issue for this feature is: [#79524] + +[#79524]: https://github.com/rust-lang/rust/issues/79524 + +------------------------ +"##, + }, + Lint { + label: "iter_is_partitioned", + description: r##"# `iter_is_partitioned` + +The tracking issue for this feature is: [#62544] + +[#62544]: https://github.com/rust-lang/rust/issues/62544 + +------------------------ +"##, + }, + Lint { + label: "iter_map_windows", + description: r##"# `iter_map_windows` + +The tracking issue for this feature is: [#87155] + +[#87155]: https://github.com/rust-lang/rust/issues/87155 + +------------------------ +"##, + }, + Lint { + label: "iter_next_chunk", + description: r##"# `iter_next_chunk` + +The tracking issue for this feature is: [#98326] + +[#98326]: https://github.com/rust-lang/rust/issues/98326 + +------------------------ +"##, + }, + Lint { + label: "iter_order_by", + description: r##"# `iter_order_by` + +The tracking issue for this feature is: [#64295] + +[#64295]: https://github.com/rust-lang/rust/issues/64295 + +------------------------ +"##, + }, + Lint { + label: "iter_partition_in_place", + description: r##"# `iter_partition_in_place` + +The tracking issue for this feature is: [#62543] + +[#62543]: https://github.com/rust-lang/rust/issues/62543 + +------------------------ +"##, + }, + Lint { + label: "iter_repeat_n", + description: r##"# `iter_repeat_n` + +The tracking issue for this feature is: [#104434] + +[#104434]: https://github.com/rust-lang/rust/issues/104434 + +------------------------ +"##, + }, + Lint { + label: "iterator_try_collect", + description: r##"# `iterator_try_collect` + +The tracking issue for this feature is: [#94047] + +[#94047]: https://github.com/rust-lang/rust/issues/94047 + +------------------------ +"##, + }, + Lint { + label: "iterator_try_reduce", + description: r##"# `iterator_try_reduce` + +The tracking issue for this feature is: [#87053] + +[#87053]: https://github.com/rust-lang/rust/issues/87053 + +------------------------ "##, }, Lint { @@ -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] -use core::intrinsics; -use core::panic::PanicInfo; extern crate libc; +extern crate unwind; + +use core::ffi::c_void; +use core::intrinsics; +use core::panic::PanicInfo; +use core::ptr::NonNull; + +pub struct Global; // the global allocator +struct Unique(NonNull); #[lang = "owned_box"] -pub struct Box(*mut T); +pub struct Box(Unique, A); + +impl Box { + pub fn new(x: T) -> Self { + #[rustc_box] + Box::new(x) + } +} + +impl Drop for Box { + fn drop(&mut self) { + unsafe { + libc::free(self.0.0.as_ptr() as *mut c_void); + } + } +} #[lang = "exchange_malloc"] unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { - let p = libc::malloc(size as 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(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: - -```rust,ignore (libc-is-finicky) -#![feature(lang_items, core_intrinsics, rustc_private)] -#![feature(start)] -#![no_std] -use core::intrinsics; -use core::panic::PanicInfo; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// Entry point for this program. -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} - -// 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() { -} - -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` - -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: - -```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; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// 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 -} - -// 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() { -} - -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` - -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'```". - -## More about the language items - -The compiler currently makes a few assumptions about symbols which are -available in the executable to call. Normally these functions are provided by -the standard library, but without it you must define your own. These symbols -are called "language items", and they each have an internal name, and then a -signature that an implementation must conform to. - -The first of these functions, `rust_eh_personality`, is used by the failure -mechanisms of the compiler. This is often mapped to GCC's personality function -(see the [libstd implementation][unwind] for more information), but crates -which do not trigger a panic can be assured that this function is never -called. The language item's name is `eh_personality`. - -[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs - -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`. - -Finally, a `eh_catch_typeinfo` static is needed for certain targets which -implement Rust panics on top of C++ exceptions. - ## List of all language items -This is a list of all language items in Rust along with where they are located in -the source code. +An up-to-date list of all language items can be found [here] in the compiler 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` +[here]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs "##, }, Lint { - label: "libstd_sys_internals", - description: r##"# `libstd_sys_internals` + label: "large_assignments", + description: r##"# `large_assignments` -This feature is internal to the Rust compiler and is not intended for general use. +The tracking issue for this feature is: [#83518] + +[#83518]: https://github.com/rust-lang/rust/issues/83518 ------------------------ "##, }, Lint { - label: "libstd_thread_internals", - description: r##"# `libstd_thread_internals` + label: "layout_for_ptr", + description: r##"# `layout_for_ptr` + +The tracking issue for this feature is: [#69835] + +[#69835]: https://github.com/rust-lang/rust/issues/69835 + +------------------------ +"##, + }, + Lint { + label: "lazy_cell", + description: r##"# `lazy_cell` + +The tracking issue for this feature is: [#109736] + +[#109736]: https://github.com/rust-lang/rust/issues/109736 + +------------------------ +"##, + }, + Lint { + label: "lazy_cell_consume", + description: r##"# `lazy_cell_consume` + +The tracking issue for this feature is: [#109736] + +[#109736]: https://github.com/rust-lang/rust/issues/109736 + +------------------------ +"##, + }, + Lint { + label: "lazy_type_alias", + description: r##"# `lazy_type_alias` + +The tracking issue for this feature is: [#112792] + +[#112792]: https://github.com/rust-lang/rust/issues/112792 + +------------------------ +"##, + }, + Lint { + label: "let_chains", + description: r##"# `let_chains` + +The tracking issue for this feature is: [#53667] + +[#53667]: https://github.com/rust-lang/rust/issues/53667 + +------------------------ +"##, + }, + Lint { + label: "liballoc_internals", + description: r##"# `liballoc_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "libstd_sys_internals", + description: r##"# `libstd_sys_internals` This feature is internal to the Rust compiler and is not intended for general use. @@ -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. +The tracking issue for this feature is: [#29603] -```rust,ignore (pseudo-code) -llvm_asm!(assembly template - : output operands - : input operands - : clobbers - : options - ); -``` +[#29603]: https://github.com/rust-lang/rust/issues/29603 -Any use of `llvm_asm` is feature gated (requires `#![feature(llvm_asm)]` on the -crate to allow) and of course requires an `unsafe` block. +------------------------ +"##, + }, + Lint { + label: "linked_list_cursors", + description: r##"# `linked_list_cursors` -> **Note**: the examples here are given in x86/x86-64 assembly, but -> all platforms are supported. +The tracking issue for this feature is: [#58533] -## Assembly template +[#58533]: https://github.com/rust-lang/rust/issues/58533 -The `assembly template` is the only required parameter and must be a -literal string (i.e. `""`) +------------------------ +"##, + }, + Lint { + label: "linked_list_remove", + description: r##"# `linked_list_remove` -```rust -#![feature(llvm_asm)] +The tracking issue for this feature is: [#69210] -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -fn foo() { - unsafe { - llvm_asm!("NOP"); - } -} +[#69210]: https://github.com/rust-lang/rust/issues/69210 -// Other platforms: -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -fn foo() { /* ... */ } +------------------------ +"##, + }, + Lint { + label: "lint_reasons", + description: r##"# `lint_reasons` -fn main() { - // ... - foo(); - // ... -} -``` +The tracking issue for this feature is: [#54503] -(The `feature(llvm_asm)` and `#[cfg]`s are omitted from now on.) +[#54503]: https://github.com/rust-lang/rust/issues/54503 -Output operands, input operands, clobbers and options are all optional -but you must add the right number of `:` if you skip them: +------------------------ +"##, + }, + Lint { + label: "linux_pidfd", + description: r##"# `linux_pidfd` -```rust -# #![feature(llvm_asm)] -# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -# fn main() { unsafe { -llvm_asm!("xor %eax, %eax" - : - : - : "eax" - ); -# } } -# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] -# fn main() {} -``` +The tracking issue for this feature is: [#82971] -Whitespace also doesn't matter: +[#82971]: https://github.com/rust-lang/rust/issues/82971 -```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: "log_syntax", + description: r##"# `log_syntax` -## Operands +The tracking issue for this feature is: [#29598] -Input and output operands follow the same format: `: -"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand -expressions must be mutable place, or not yet assigned: +[#29598]: https://github.com/rust-lang/rust/issues/29598 -```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 } +------------------------ +"##, + }, + Lint { + label: "macro_metavar_expr", + description: r##"# `macro_metavar_expr` -fn main() { - assert_eq!(add(3, 14159), 14162) -} -``` +The tracking issue for this feature is: [#83527] -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: +[#83527]: https://github.com/rust-lang/rust/issues/83527 -```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 -# } -``` +------------------------ +"##, + }, + Lint { + label: "map_entry_replace", + description: r##"# `map_entry_replace` -## Clobbers +The tracking issue for this feature is: [#44286] -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. +[#44286]: https://github.com/rust-lang/rust/issues/44286 -```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() {} -``` +------------------------ +"##, + }, + Lint { + label: "map_many_mut", + description: r##"# `map_many_mut` -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. +The tracking issue for this feature is: [#97601] -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. +[#97601]: https://github.com/rust-lang/rust/issues/97601 -## Options +------------------------ +"##, + }, + Lint { + label: "map_try_insert", + description: r##"# `map_try_insert` -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: +The tracking issue for this feature is: [#82766] -Current valid options are: +[#82766]: https://github.com/rust-lang/rust/issues/82766 -1. `volatile` - specifying this is analogous to - `__asm__ __volatile__ (...)` in gcc/clang. -2. `alignstack` - certain instructions expect the stack to be - aligned a certain way (i.e. SSE) and specifying this indicates to - the compiler to insert its usual stack alignment code -3. `intel` - use intel syntax instead of the default AT&T. - -```rust -# #![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() {} -``` - -## More Information - -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. - -[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions +------------------------ "##, }, Lint { @@ -3302,6 +6216,116 @@ fn cheap_clone(t: T) -> T { This is expected to replace the unstable `overlapping_marker_traits` feature, which applied to all empty traits (without needing an opt-in). +"##, + }, + Lint { + label: "maybe_uninit_array_assume_init", + description: r##"# `maybe_uninit_array_assume_init` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_as_bytes", + description: r##"# `maybe_uninit_as_bytes` + +The tracking issue for this feature is: [#93092] + +[#93092]: https://github.com/rust-lang/rust/issues/93092 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_slice", + description: r##"# `maybe_uninit_slice` + +The tracking issue for this feature is: [#63569] + +[#63569]: https://github.com/rust-lang/rust/issues/63569 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_uninit_array", + description: r##"# `maybe_uninit_uninit_array` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_uninit_array_transpose", + description: r##"# `maybe_uninit_uninit_array_transpose` + +The tracking issue for this feature is: [#96097] + +[#96097]: https://github.com/rust-lang/rust/issues/96097 + +------------------------ +"##, + }, + Lint { + label: "maybe_uninit_write_slice", + description: r##"# `maybe_uninit_write_slice` + +The tracking issue for this feature is: [#79995] + +[#79995]: https://github.com/rust-lang/rust/issues/79995 + +------------------------ +"##, + }, + Lint { + label: "mem_copy_fn", + description: r##"# `mem_copy_fn` + +The tracking issue for this feature is: [#98262] + +[#98262]: https://github.com/rust-lang/rust/issues/98262 + +------------------------ +"##, + }, + Lint { + label: "min_specialization", + description: r##"# `min_specialization` + +The tracking issue for this feature is: [#31844] + +[#31844]: https://github.com/rust-lang/rust/issues/31844 + +------------------------ +"##, + }, + Lint { + label: "mips_target_feature", + description: r##"# `mips_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "more_float_constants", + description: r##"# `more_float_constants` + +The tracking issue for this feature is: [#103883] + +[#103883]: https://github.com/rust-lang/rust/issues/103883 + +------------------------ "##, }, Lint { @@ -3338,18 +6362,56 @@ 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. ------------------------ +"##, + }, + Lint { + label: "must_not_suspend", + description: r##"# `must_not_suspend` -The `native_link_modifiers` feature allows you to use the `modifiers` syntax with the `#[link(..)]` attribute. +The tracking issue for this feature is: [#83310] -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. +[#83310]: https://github.com/rust-lang/rust/issues/83310 + +------------------------ +"##, + }, + Lint { + label: "mutex_unlock", + description: r##"# `mutex_unlock` + +The tracking issue for this feature is: [#81872] + +[#81872]: https://github.com/rust-lang/rust/issues/81872 + +------------------------ +"##, + }, + Lint { + label: "mutex_unpoison", + description: r##"# `mutex_unpoison` + +The tracking issue for this feature is: [#96469] + +[#96469]: https://github.com/rust-lang/rust/issues/96469 + +------------------------ +"##, + }, + Lint { + label: "naked_functions", + description: r##"# `naked_functions` + +The tracking issue for this feature is: [#32408] + +[#32408]: https://github.com/rust-lang/rust/issues/32408 + +------------------------ "##, }, Lint { @@ -3375,72 +6437,23 @@ The default for this modifier is unclear, some targets currently specify it as ` "##, }, Lint { - label: "native_link_modifiers_bundle", - description: r##"# `native_link_modifiers_bundle` + 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 ------------------------ - -The `native_link_modifiers_bundle` feature allows you to use the `bundle` modifier. - -Only compatible with the `static` linking kind. Using any other kind will result in a compiler error. - -`+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. - -`-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. - -This modifier is supposed to supersede the `static-nobundle` linking kind defined by [RFC 1717](https://github.com/rust-lang/rfcs/pull/1717). - -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: "negative_bounds", + description: r##"# `negative_bounds` -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_verbatim` feature allows you to use the `verbatim` modifier. - -`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes (like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the linker. - -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. - -The default for this modifier is `-verbatim`. - -This RFC changes the behavior of `raw-dylib` linking kind specified by [RFC 2627](https://github.com/rust-lang/rfcs/pull/2627). The `.dll` suffix (or other target-specified suffixes for other targets) is now added automatically. -If your DLL doesn't have the `.dll` suffix, it can be specified with `+verbatim`. -"##, - }, - Lint { - label: "native_link_modifiers_whole_archive", - description: r##"# `native_link_modifiers_whole_archive` - -The tracking issue for this feature is: [#81490] - -[#81490]: https://github.com/rust-lang/rust/issues/81490 - ------------------------- - -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. - -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 { @@ -3569,6 +6592,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 { @@ -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. @@ -3689,6 +7023,88 @@ conversion. You can run `rustc -W help foo.rs` to see a list of lints known to `rustc`, including those provided by plugins loaded by `foo.rs`. +"##, + }, + Lint { + label: "pointer_byte_offsets", + description: r##"# `pointer_byte_offsets` + +The tracking issue for this feature is: [#96283] + +[#96283]: https://github.com/rust-lang/rust/issues/96283 + +------------------------ +"##, + }, + Lint { + label: "pointer_is_aligned", + description: r##"# `pointer_is_aligned` + +The tracking issue for this feature is: [#96284] + +[#96284]: https://github.com/rust-lang/rust/issues/96284 + +------------------------ +"##, + }, + Lint { + label: "pointer_like_trait", + description: r##"# `pointer_like_trait` + +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 { @@ -3697,6 +7113,123 @@ including those provided by plugins loaded by `foo.rs`. This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + 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. + ------------------------ "##, }, @@ -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] -## Limitations +[#75402]: https://github.com/rust-lang/rust/issues/75402 -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. +------------------------ +"##, + }, + Lint { + label: "ptr_from_ref", + description: r##"# `ptr_from_ref` -On the `i686-pc-windows-msvc` target, this feature supports only the `cdecl`, `stdcall`, `system`, and `fastcall` -calling conventions. +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 + +------------------------ +"##, + }, + 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] + +[#95595]: https://github.com/rust-lang/rust/issues/95595 + +------------------------ +"##, + }, + 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 { @@ -3776,6 +7472,103 @@ enum Foo { Bar(u64), } ``` +"##, + }, + 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 { @@ -3784,6 +7577,39 @@ enum Foo { This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + 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 + ------------------------ "##, }, @@ -3842,6 +7668,326 @@ error: size: Size { raw: 16 } 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 { @@ -3850,6 +7996,184 @@ error: aborting due to 2 previous errors This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + 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 + ------------------------ "##, }, @@ -3859,6 +8183,186 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + 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 + ------------------------ "##, }, @@ -4022,6 +8526,57 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured However, the optimizer can still modify a testcase in an undesirable manner even when using either of the above. +"##, + }, + Lint { + label: "test_2018_feature", + description: r##"# `test_2018_feature` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "test_unstable_lint", + description: r##"# `test_unstable_lint` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "thin_box", + description: r##"# `thin_box` + +The tracking issue for this feature is: [#92791] + +[#92791]: https://github.com/rust-lang/rust/issues/92791 + +------------------------ +"##, + }, + Lint { + label: "thread_id_value", + description: r##"# `thread_id_value` + +The tracking issue for this feature is: [#67939] + +[#67939]: https://github.com/rust-lang/rust/issues/67939 + +------------------------ +"##, + }, + Lint { + label: "thread_local", + description: r##"# `thread_local` + +The tracking issue for this feature is: [#29594] + +[#29594]: https://github.com/rust-lang/rust/issues/29594 + +------------------------ "##, }, Lint { @@ -4030,6 +8585,28 @@ even when using either of the above. This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "thread_sleep_until", + description: r##"# `thread_sleep_until` + +The tracking issue for this feature is: [#113752] + +[#113752]: https://github.com/rust-lang/rust/issues/113752 + +------------------------ +"##, + }, + Lint { + label: "thread_spawn_unchecked", + description: r##"# `thread_spawn_unchecked` + +The tracking issue for this feature is: [#55132] + +[#55132]: https://github.com/rust-lang/rust/issues/55132 + ------------------------ "##, }, @@ -4074,6 +8651,17 @@ note: trace_macro Finished dev [unoptimized + debuginfo] target(s) in 0.60 secs ``` +"##, + }, + Lint { + label: "track_path", + description: r##"# `track_path` + +The tracking issue for this feature is: [#99515] + +[#99515]: https://github.com/rust-lang/rust/issues/99515 + +------------------------ "##, }, Lint { @@ -4143,6 +8731,28 @@ impl Bar for T {} let bar: &dyn Bar = &123; let foo: &dyn Foo = bar; ``` +"##, + }, + Lint { + label: "transmutability", + description: r##"# `transmutability` + +The tracking issue for this feature is: [#99571] + +[#99571]: https://github.com/rust-lang/rust/issues/99571 + +------------------------ +"##, + }, + Lint { + label: "transmute_generic_consts", + description: r##"# `transmute_generic_consts` + +The tracking issue for this feature is: [#109929] + +[#109929]: https://github.com/rust-lang/rust/issues/109929 + +------------------------ "##, }, Lint { @@ -4230,6 +8840,59 @@ example, it is unspecified whether `size_of::()` is equal to it is transparent). The Rust compiler is free to perform this optimization if possible, but is not required to, and different compiler versions may differ in their application of these optimizations. +"##, + }, + Lint { + label: "trivial_bounds", + description: r##"# `trivial_bounds` + +The tracking issue for this feature is: [#48214] + +[#48214]: https://github.com/rust-lang/rust/issues/48214 + +------------------------ +"##, + }, + Lint { + label: "trusted_len", + description: r##"# `trusted_len` + +The tracking issue for this feature is: [#37572] + +[#37572]: https://github.com/rust-lang/rust/issues/37572 + +------------------------ +"##, + }, + Lint { + label: "trusted_len_next_unchecked", + description: r##"# `trusted_len_next_unchecked` + +The tracking issue for this feature is: [#37572] + +[#37572]: https://github.com/rust-lang/rust/issues/37572 + +------------------------ +"##, + }, + Lint { + label: "trusted_random_access", + description: r##"# `trusted_random_access` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "trusted_step", + description: r##"# `trusted_step` + +The tracking issue for this feature is: [#85731] + +[#85731]: https://github.com/rust-lang/rust/issues/85731 + +------------------------ "##, }, Lint { @@ -4264,6 +8927,92 @@ let result: Result = try { }; 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 { @@ -4301,6 +9050,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 { @@ -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)] @@ -4330,6 +9112,200 @@ extern "rust-call" fn add_args(args: (u32, u32)) -> u32 { 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 { @@ -4540,6 +9516,17 @@ fn main() { ``` [RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md +"##, + }, + Lint { + label: "unwrap_infallible", + description: r##"# `unwrap_infallible` + +The tracking issue for this feature is: [#61695] + +[#61695]: https://github.com/rust-lang/rust/issues/61695 + +------------------------ "##, }, Lint { @@ -4548,6 +9535,149 @@ fn main() { This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "used_with_arg", + description: r##"# `used_with_arg` + +The tracking issue for this feature is: [#93798] + +[#93798]: https://github.com/rust-lang/rust/issues/93798 + +------------------------ +"##, + }, + Lint { + label: "utf16_extra", + description: r##"# `utf16_extra` + +The tracking issue for this feature is: [#94919] + +[#94919]: https://github.com/rust-lang/rust/issues/94919 + +------------------------ +"##, + }, + Lint { + label: "utf16_extra_const", + description: r##"# `utf16_extra_const` + +The tracking issue for this feature is: [#94919] + +[#94919]: https://github.com/rust-lang/rust/issues/94919 + +------------------------ +"##, + }, + Lint { + label: "utf8_chunks", + description: r##"# `utf8_chunks` + +The tracking issue for this feature is: [#99543] + +[#99543]: https://github.com/rust-lang/rust/issues/99543 + +------------------------ +"##, + }, + Lint { + label: "variant_count", + description: r##"# `variant_count` + +The tracking issue for this feature is: [#73662] + +[#73662]: https://github.com/rust-lang/rust/issues/73662 + +------------------------ +"##, + }, + Lint { + label: "vec_into_raw_parts", + description: r##"# `vec_into_raw_parts` + +The tracking issue for this feature is: [#65816] + +[#65816]: https://github.com/rust-lang/rust/issues/65816 + +------------------------ +"##, + }, + Lint { + label: "vec_push_within_capacity", + description: r##"# `vec_push_within_capacity` + +The tracking issue for this feature is: [#100486] + +[#100486]: https://github.com/rust-lang/rust/issues/100486 + +------------------------ +"##, + }, + Lint { + label: "vec_split_at_spare", + description: r##"# `vec_split_at_spare` + +The tracking issue for this feature is: [#81944] + +[#81944]: https://github.com/rust-lang/rust/issues/81944 + +------------------------ +"##, + }, + Lint { + label: "waker_getters", + description: r##"# `waker_getters` + +The tracking issue for this feature is: [#87021] + +[#87021]: https://github.com/rust-lang/rust/issues/87021 + +------------------------ +"##, + }, + Lint { + label: "wasi_ext", + description: r##"# `wasi_ext` + +The tracking issue for this feature is: [#71213] + +[#71213]: https://github.com/rust-lang/rust/issues/71213 + +------------------------ +"##, + }, + Lint { + label: "wasm_abi", + description: r##"# `wasm_abi` + +The tracking issue for this feature is: [#83788] + +[#83788]: https://github.com/rust-lang/rust/issues/83788 + +------------------------ +"##, + }, + Lint { + label: "wasm_target_feature", + description: r##"# `wasm_target_feature` + +The tracking issue for this feature is: [#44839] + +[#44839]: https://github.com/rust-lang/rust/issues/44839 + +------------------------ +"##, + }, + Lint { + label: "windows_by_handle", + description: r##"# `windows_by_handle` + +The tracking issue for this feature is: [#63010] + +[#63010]: https://github.com/rust-lang/rust/issues/63010 + ------------------------ "##, }, @@ -4575,6 +9705,59 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "windows_process_exit_code_from", + description: r##"# `windows_process_exit_code_from` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_async_pipes", + description: r##"# `windows_process_extensions_async_pipes` + +The tracking issue for this feature is: [#98289] + +[#98289]: https://github.com/rust-lang/rust/issues/98289 + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_force_quotes", + description: r##"# `windows_process_extensions_force_quotes` + +The tracking issue for this feature is: [#82227] + +[#82227]: https://github.com/rust-lang/rust/issues/82227 + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_main_thread_handle", + description: r##"# `windows_process_extensions_main_thread_handle` + +The tracking issue for this feature is: [#96723] + +[#96723]: https://github.com/rust-lang/rust/issues/96723 + +------------------------ +"##, + }, + Lint { + label: "windows_process_extensions_raw_attribute", + description: r##"# `windows_process_extensions_raw_attribute` + +The tracking issue for this feature is: [#114854] + +[#114854]: https://github.com/rust-lang/rust/issues/114854 + ------------------------ "##, }, @@ -4585,17 +9768,129 @@ This feature is internal to the Rust compiler and is not intended for general us This feature is internal to the Rust compiler and is not intended for general use. ------------------------ +"##, + }, + Lint { + label: "with_negative_coherence", + description: r##"# `with_negative_coherence` + +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 { + do yeet 4; +} +assert_eq!(foo(), Err(4)); + +fn bar() -> Option { + do yeet; +} +assert_eq!(bar(), None); +``` "##, }, ]; pub const CLIPPY_LINTS: &[Lint] = &[ + Lint { + label: "clippy::absolute_paths", + description: r##"Checks for usage of items through absolute paths, like `std::env::current_dir`."##, + }, Lint { label: "clippy::absurd_extreme_comparisons", description: r##"Checks for comparisons where one side of the relation is either the minimum or maximum value for its type and warns if it involves a case that is always true or always false. Only integer and boolean types are checked."##, + }, + Lint { + label: "clippy::alloc_instead_of_core", + description: r##"Finds items imported through `alloc` when available through `core`."##, + }, + Lint { + label: "clippy::allow_attributes", + description: r##"Checks for usage of the `#[allow]` attribute and suggests replacing it with +the `#[expect]` (See [RFC 2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html)) + +The expect attribute is still unstable and requires the `lint_reasons` +on nightly. It can be enabled by adding `#![feature(lint_reasons)]` to +the crate root. + +This lint only warns outer attributes (`#[allow]`), as inner attributes +(`#![allow]`) are usually used to enable or disable lints on a global scale."##, + }, + Lint { + label: "clippy::allow_attributes_without_reason", + description: r##"Checks for attributes that allow lints without a reason. + +(This requires the `lint_reasons` feature)"##, + }, + Lint { + label: "clippy::almost_complete_range", + description: r##"Checks for ranges which almost include the entire range of letters from 'a' to 'z' +or digits from '0' to '9', but don't because they're a half open range."##, }, Lint { label: "clippy::almost_swapped", @@ -4609,6 +9904,22 @@ constants which are defined in or [`std::f64::consts`](https://doc.rust-lang.org/stable/std/f64/consts/#constants), respectively, suggesting to use the predefined constant."##, + }, + Lint { + label: "clippy::arc_with_non_send_sync", + description: r##". +This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`."##, + }, + Lint { + label: "clippy::arithmetic_side_effects", + description: r##"Checks any kind of arithmetic operation of any type. + +Operators like `+`, `-`, `*` or `<<` are usually capable of overflowing according to the [Rust +Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow), +or can panic (`/`, `%`). + +Known safe built-in types like `Wrapping` or `Saturating`, floats, operations in constant +environments, allowed types and non-constant operations that won't overflow are ignored."##, }, Lint { label: "clippy::as_conversions", @@ -4617,15 +9928,27 @@ respectively, suggesting to use the predefined constant."##, Note that this lint is specialized in linting *every single* use of `as` regardless of whether good alternatives exist or not. If you want more precise lints for `as`, please consider using these separate lints: -`unnecessary_cast`, `cast_lossless/possible_truncation/possible_wrap/precision_loss/sign_loss`, +`unnecessary_cast`, `cast_lossless/cast_possible_truncation/cast_possible_wrap/cast_precision_loss/cast_sign_loss`, `fn_to_numeric_cast(_with_truncation)`, `char_lit_as_u8`, `ref_to_mut` and `ptr_as_ptr`. There is a good explanation the reason why this lint should work in this way and how it is useful [in this issue](https://github.com/rust-lang/rust-clippy/issues/5122)."##, }, + Lint { + label: "clippy::as_ptr_cast_mut", + description: r##"Checks for the result of a `&self`-taking `as_ptr` being cast to a mutable pointer"##, + }, + Lint { + label: "clippy::as_underscore", + description: r##"Checks for the usage of `as _` conversion using inferred type."##, + }, Lint { label: "clippy::assertions_on_constants", description: r##"Checks for `assert!(true)` and `assert!(false)` calls."##, }, + Lint { + label: "clippy::assertions_on_result_states", + description: r##"Checks for `assert!(r.is_ok())` or `assert!(r.is_err())` calls."##, + }, Lint { label: "clippy::assign_op_pattern", description: r##"Checks for `a = a op b` or `a = b commutative_op a` @@ -4639,16 +9962,19 @@ patterns."##, label: "clippy::async_yields_async", description: r##"Checks for async blocks that yield values of types that can themselves be awaited."##, + }, + Lint { + label: "clippy::await_holding_invalid_type", + description: r##"Allows users to configure types which should not be held across `await` +suspension points."##, }, Lint { label: "clippy::await_holding_lock", - description: r##"Checks for calls to await while holding a -non-async-aware MutexGuard."##, + description: r##"Checks for calls to await while holding a non-async-aware MutexGuard."##, }, Lint { label: "clippy::await_holding_refcell_ref", - description: r##"Checks for calls to await while holding a -`RefCell` `Ref` or `RefMut`."##, + description: r##"Checks for calls to await while holding a `RefCell` `Ref` or `RefMut`."##, }, Lint { label: "clippy::bad_bit_mask", @@ -4659,24 +9985,23 @@ The formula for detecting if an expression of the type `_ m {`!=`, `>=`, `>`, `!=`, `>=`, `>`}) can be determined from the following table: -|Comparison |Bit Op|Example |is always|Formula | -|------------|------|------------|---------|----------------------| -|`==` or `!=`| `&` |`x & 2 == 3`|`false` |`c & m != c` | -|`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | -|`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | -|`==` or `!=`| `|` |`x | 1 == 0`|`false` |`c | m != c` | -|`<` or `>=`| `|` |`x | 1 < 1` |`false` |`m >= c` | -|`<=` or `>` | `|` |`x | 1 > 0` |`true` |`m > c` |"##, +|Comparison |Bit Op|Example |is always|Formula | +|------------|------|-------------|---------|----------------------| +|`==` or `!=`| `&` |`x & 2 == 3` |`false` |`c & m != c` | +|`<` or `>=`| `&` |`x & 2 < 3` |`true` |`m < c` | +|`>` or `<=`| `&` |`x & 1 > 1` |`false` |`m <= c` | +|`==` or `!=`| `\\|` |`x \\| 1 == 0`|`false` |`c \\| m != c` | +|`<` or `>=`| `\\|` |`x \\| 1 < 1` |`false` |`m >= c` | +|`<=` or `>` | `\\|` |`x \\| 1 > 0` |`true` |`m > c` |"##, + }, + Lint { + label: "clippy::big_endian_bytes", + description: r##"Checks for the usage of the `to_be_bytes` method and/or the function `from_be_bytes`."##, }, Lint { label: "clippy::bind_instead_of_map", description: r##"Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))` or `_.or_else(|x| Err(y))`."##, - }, - Lint { - label: "clippy::blacklisted_name", - description: r##"Checks for usage of blacklisted names for variables, such -as `foo`."##, }, Lint { label: "clippy::blanket_clippy_restriction_lints", @@ -4697,6 +10022,18 @@ expression, statements or conditions that use closures with blocks."##, `x != true` and order comparisons such as `x < true` (or vice versa) and suggest using the variable directly."##, }, + Lint { + label: "clippy::bool_to_int_with_if", + description: r##"Instead of using an if statement to convert a bool to an int, +this lint suggests using a `from()` function or an `as` coercion."##, + }, + Lint { + label: "clippy::borrow_as_ptr", + description: r##"Checks for the usage of `&expr as *const T` or +`&mut expr as *mut T`, and suggest using `ptr::addr_of` or +`ptr::addr_of_mut` instead."##, + }, + Lint { label: "clippy::borrow_deref_ref", description: r##"Checks for `&*(&T)`."## }, Lint { label: "clippy::borrow_interior_mutable_const", description: r##"Checks if `const` items which is interior mutable (e.g., @@ -4704,13 +10041,18 @@ contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.) has been borrowed directly."##, }, Lint { label: "clippy::borrowed_box", - description: r##"Checks for use of `&Box` anywhere in the code. + description: r##"Checks for usage of `&Box` anywhere in the code. Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##, }, Lint { label: "clippy::box_collection", - description: r##"Checks for use of `Box` where T is a collection such as Vec anywhere in the code. + description: r##"Checks for usage of `Box` where T is a collection such as Vec anywhere in the code. Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##, + }, + Lint { + label: "clippy::box_default", + description: r##"checks for `Box::new(T::default())`, which is better written as +`Box::::default()`."##, }, Lint { label: "clippy::boxed_local", @@ -4726,6 +10068,11 @@ moved out of the blocks."##, label: "clippy::builtin_type_shadow", description: r##"Warns if a generic shadows a built-in type."##, }, + Lint { + label: "clippy::bytes_count_to_len", + description: r##"It checks for `str::bytes().count()` and suggests replacing it with +`str::len()`."##, + }, Lint { label: "clippy::bytes_nth", description: r##"Checks for the use of `.bytes().nth()`."##, @@ -4739,24 +10086,43 @@ moved out of the blocks."##, label: "clippy::case_sensitive_file_extension_comparisons", description: r##"Checks for calls to `ends_with` with possible file extensions and suggests to use a case-insensitive approach instead."##, + }, + Lint { + label: "clippy::cast_abs_to_unsigned", + description: r##"Checks for usage of the `abs()` method that cast the result to unsigned."##, + }, + Lint { + label: "clippy::cast_enum_constructor", + description: r##"Checks for casts from an enum tuple constructor to an integer."##, + }, + Lint { + label: "clippy::cast_enum_truncation", + description: r##"Checks for casts from an enum type to an integral type which will definitely truncate the +value."##, }, Lint { label: "clippy::cast_lossless", description: r##"Checks for casts between numerical types that may be replaced by safe conversion functions."##, }, + Lint { + label: "clippy::cast_nan_to_int", + description: r##"Checks for a known NaN float being cast to an integer"##, + }, Lint { label: "clippy::cast_possible_truncation", description: r##"Checks for casts between numerical types that may truncate large values. This is expected behavior, so the cast is `Allow` by -default."##, +default. It suggests user either explicitly ignore the lint, +or use `try_from()` and handle the truncation, default, or panic explicitly."##, }, Lint { label: "clippy::cast_possible_wrap", description: r##"Checks for casts from an unsigned type to a signed type of -the same size. Performing such a cast is a 'no-op' for the compiler, -i.e., nothing is changed at the bit level, and the binary representation of -the value is reinterpreted. This can cause wrapping if the value is too big +the same size, or possibly smaller due to target dependent integers. +Performing such a cast is a 'no-op' for the compiler, i.e., nothing is +changed at the bit level, and the binary representation of the value is +reinterpreted. This can cause wrapping if the value is too big for the target signed type. However, the cast works as defined, so this lint is `Allow` by default."##, }, @@ -4775,10 +10141,6 @@ or any 64-bit integer to `f64`."##, description: r##"Checks for casts, using `as` or `pointer::cast`, from a less-strictly-aligned pointer to a more-strictly-aligned pointer"##, }, - Lint { - label: "clippy::cast_ref_to_mut", - description: r##"Checks for casts of `&T` to `&mut T` anywhere in the code."##, - }, Lint { label: "clippy::cast_sign_loss", description: r##"Checks for casts from a signed to an unsigned numerical @@ -4786,6 +10148,14 @@ type. In this case, negative values wrap around to large positive values, which can be quite surprising in practice. However, as the cast works as defined, this lint is `Allow` by default."##, }, + Lint { + label: "clippy::cast_slice_different_sizes", + description: r##"Checks for `as` casts between raw pointers to slices with differently sized elements."##, + }, + Lint { + label: "clippy::cast_slice_from_raw_parts", + description: r##"Checks for a raw slice being cast to a slice pointer"##, + }, Lint { label: "clippy::char_lit_as_u8", description: r##"Checks for expressions where a character literal is cast @@ -4806,8 +10176,8 @@ if it starts with a given char."##, description: r##"Checks for explicit bounds checking when casting."##, }, Lint { - label: "clippy::clone_double_ref", - description: r##"Checks for usage of `.clone()` on an `&&T`."##, + label: "clippy::clear_with_drain", + description: r##"Checks for usage of `.drain(..)` for the sole purpose of clearing a container."##, }, Lint { label: "clippy::clone_on_copy", @@ -4821,10 +10191,9 @@ function syntax instead (e.g., `Rc::clone(foo)`)."##, }, Lint { label: "clippy::cloned_instead_of_copied", - description: r##"Checks for usages of `cloned()` on an `Iterator` or `Option` where + description: r##"Checks for usage of `cloned()` on an `Iterator` or `Option` where `copied()` could be used instead."##, }, - Lint { label: "clippy::cmp_nan", description: r##"Checks for comparisons to NaN."## }, Lint { label: "clippy::cmp_null", description: r##"This lint checks for equality comparisons with `ptr::null`"##, @@ -4856,6 +10225,15 @@ without adding any branches. Note that this lint is not intended to find _all_ cases where nested match patterns can be merged, but only cases where merging would most likely make the code more readable."##, }, + Lint { + label: "clippy::collapsible_str_replace", + description: r##"Checks for consecutive calls to `str::replace` (2 or more) +that can be collapsed into a single call."##, + }, + Lint { + label: "clippy::collection_is_never_read", + description: r##"Checks for collections that are never queried."##, + }, Lint { label: "clippy::comparison_chain", description: r##"Checks comparison chains written with `if` that can be @@ -4871,6 +10249,10 @@ and suggests using `.is_empty()` where applicable."##, description: r##"Checks for types that implement `Copy` as well as `Iterator`."##, }, + Lint { + label: "clippy::crate_in_macro_def", + description: r##"Checks for usage of `crate` as opposed to `$crate` in a macro definition."##, + }, Lint { label: "clippy::create_dir", description: r##"Checks usage of `std::fs::create_dir` and suggest using `std::fs::create_dir_all` instead."##, @@ -4879,7 +10261,10 @@ and suggests using `.is_empty()` where applicable."##, label: "clippy::crosspointer_transmute", description: r##"Checks for transmutes between a type `T` and `*T`."##, }, - Lint { label: "clippy::dbg_macro", description: r##"Checks for usage of dbg!() macro."## }, + Lint { + label: "clippy::dbg_macro", + description: r##"Checks for usage of the [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro."##, + }, Lint { label: "clippy::debug_assert_with_mut_call", description: r##"Checks for function/method calls with a mutable @@ -4893,6 +10278,15 @@ parameter in `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!` macros." label: "clippy::declare_interior_mutable_const", description: r##"Checks for declaration of `const` items which is interior mutable (e.g., contains a `Cell`, `Mutex`, `AtomicXxxx`, etc.)."##, + }, + Lint { + label: "clippy::default_constructed_unit_structs", + description: r##"Checks for construction on unit struct using `default`."##, + }, + Lint { + label: "clippy::default_instead_of_iter_empty", + description: r##"It checks for `std::iter::Empty::default()` and suggests replacing it with +`std::iter::empty()`."##, }, Lint { label: "clippy::default_numeric_fallback", @@ -4909,6 +10303,10 @@ See [RFC0212](https://github.com/rust-lang/rfcs/blob/master/text/0212-restore-in label: "clippy::default_trait_access", description: r##"Checks for literal calls to `Default::default()`."##, }, + Lint { + label: "clippy::default_union_representation", + description: r##"Displays a warning when a union is declared with the default representation (without a `#[repr(C)]` attribute)."##, + }, Lint { label: "clippy::deprecated_cfg_attr", description: r##"Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it @@ -4923,23 +10321,47 @@ field that is not a valid semantic version."##, label: "clippy::deref_addrof", description: r##"Checks for usage of `*&` and `*&mut` in expressions."##, }, + Lint { + label: "clippy::deref_by_slicing", + description: r##"Checks for slicing expressions which are equivalent to dereferencing the +value."##, + }, Lint { label: "clippy::derivable_impls", description: r##"Detects manual `std::default::Default` implementations that are identical to a derived implementation."##, }, Lint { - label: "clippy::derive_hash_xor_eq", - description: r##"Checks for deriving `Hash` but implementing `PartialEq` -explicitly or vice versa."##, + label: "clippy::derive_ord_xor_partial_ord", + description: r##"Lints against manual `PartialOrd` and `Ord` implementations for types with a derived `Ord` +or `PartialOrd` implementation."##, }, Lint { - label: "clippy::derive_ord_xor_partial_ord", - description: r##"Checks for deriving `Ord` but implementing `PartialOrd` -explicitly or vice versa."##, + label: "clippy::derive_partial_eq_without_eq", + description: r##"Checks for types that derive `PartialEq` and could implement `Eq`."##, + }, + Lint { + label: "clippy::derived_hash_with_manual_eq", + description: r##"Lints against manual `PartialEq` implementations for types with a derived `Hash` +implementation."##, + }, + Lint { + label: "clippy::disallowed_macros", + description: r##"Denies the configured macros in clippy.toml + +Note: Even though this lint is warn-by-default, it will only trigger if +macros are defined in the clippy.toml file."##, }, Lint { label: "clippy::disallowed_methods", - description: r##"Denies the configured methods and functions in clippy.toml"##, + description: r##"Denies the configured methods and functions in clippy.toml + +Note: Even though this lint is warn-by-default, it will only trigger if +methods are defined in the clippy.toml file."##, + }, + Lint { + label: "clippy::disallowed_names", + description: r##"Checks for usage of disallowed names for variables, such +as `foo`."##, }, Lint { label: "clippy::disallowed_script_idents", @@ -4958,12 +10380,20 @@ See also: [`non_ascii_idents`]. }, Lint { label: "clippy::disallowed_types", - description: r##"Denies the configured types in clippy.toml."##, + description: r##"Denies the configured types in clippy.toml. + +Note: Even though this lint is warn-by-default, it will only trigger if +types are defined in the clippy.toml file."##, }, Lint { label: "clippy::diverging_sub_expression", description: r##"Checks for diverging calls that are not match arms or statements."##, + }, + Lint { + label: "clippy::doc_link_with_quotes", + description: r##"Detects the syntax `['foo']` in documentation comments (notice quotes instead of backticks) +outside of code blocks"##, }, Lint { label: "clippy::doc_markdown", @@ -4989,14 +10419,19 @@ marked as `#[must_use]`."##, description: r##"Checks for unnecessary double parentheses."##, }, Lint { - label: "clippy::drop_copy", - description: r##"Checks for calls to `std::mem::drop` with a value -that derives the Copy trait"##, + label: "clippy::drain_collect", + description: r##"Checks for calls to `.drain()` that clear the collection, immediately followed by a call to `.collect()`. + +> Collection in this context refers to any type with a `drain` method: +> `Vec`, `VecDeque`, `BinaryHeap`, `HashSet`,`HashMap`, `String`"##, }, Lint { - label: "clippy::drop_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", @@ -5013,6 +10448,10 @@ from other `Duration` methods."##, description: r##"Checks for usage of if expressions with an `else if` branch, but without a final `else` branch."##, }, + Lint { + label: "clippy::empty_drop", + description: r##"Checks for empty `Drop` implementations."##, + }, Lint { label: "clippy::empty_enum", description: r##"Checks for `enum`s with no variants. @@ -5021,11 +10460,19 @@ As of this writing, the `never_type` is still a nightly-only experimental API. Therefore, this lint is only triggered if the `never_type` is enabled."##, }, + Lint { + label: "clippy::empty_line_after_doc_comments", + description: r##"Checks for empty lines after documenation comments."##, + }, Lint { label: "clippy::empty_line_after_outer_attr", description: r##"Checks for empty lines after outer attributes"##, }, Lint { label: "clippy::empty_loop", description: r##"Checks for empty `loop` expressions."## }, + Lint { + label: "clippy::empty_structs_with_brackets", + description: r##"Finds structs without fields (a so-called empty struct) that are declared with brackets."##, + }, Lint { label: "clippy::enum_clike_unportable_variant", description: r##"Checks for C-like enumerations that are @@ -5052,10 +10499,18 @@ bitwise, difference and division binary operators (`==`, `>`, etc., `&&`, description: r##"Checks for erasing operations, e.g., `x * 0`."##, }, Lint { - label: "clippy::eval_order_dependence", - description: r##"Checks for a read and a write to the same variable where -whether the read occurs before or after the write depends on the evaluation -order of sub-expressions."##, + label: "clippy::err_expect", + description: r##"Checks for `.err().expect()` calls on the `Result` type."##, + }, + Lint { + label: "clippy::error_impl_error", + description: r##"Checks for types named `Error` that implement `Error`."##, + }, + Lint { + label: "clippy::excessive_nesting", + description: r##"Checks for blocks which are nested beyond a certain threshold. + +Note: Even though this lint is warn-by-default, it will only trigger if a maximum nesting level is defined in the clippy.toml file."##, }, Lint { label: "clippy::excessive_precision", @@ -5072,8 +10527,7 @@ than that supported by the underlying type."##, }, Lint { label: "clippy::exit", - description: r##"`exit()` terminates the program and doesn't provide a -stack trace."##, + description: r##"Detects calls to the `exit()` function which terminates the program."##, }, Lint { label: "clippy::expect_fun_call", @@ -5082,13 +10536,17 @@ etc., and suggests to use `unwrap_or_else` instead"##, }, Lint { label: "clippy::expect_used", - description: r##"Checks for `.expect()` calls on `Option`s and `Result`s."##, + description: r##"Checks for `.expect()` or `.expect_err()` calls on `Result`s and `.expect()` call on `Option`s."##, }, Lint { label: "clippy::expl_impl_clone_on_copy", description: r##"Checks for explicit `Clone` implementations for `Copy` types."##, }, + Lint { + label: "clippy::explicit_auto_deref", + description: r##"Checks for dereferencing expressions which would be covered by auto-deref."##, + }, Lint { label: "clippy::explicit_counter_loop", description: r##"Checks `for` loops over slices with an explicit counter @@ -5126,6 +10584,10 @@ replaced with `(e)print!()` / `(e)println!()`"##, description: r##"Checks for lifetimes in generics that are never used anywhere else."##, }, + Lint { + label: "clippy::extra_unused_type_parameters", + description: r##"Checks for type parameters in generics that are never used anywhere else."##, + }, Lint { label: "clippy::fallible_impl_from", description: r##"Checks for impls of `From<..>` that contain `panic!()` or `unwrap()`"##, @@ -5143,6 +10605,10 @@ with Default::default()."##, label: "clippy::filter_map", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { + label: "clippy::filter_map_bool_then", + description: r##"Checks for usage of `bool::then` in `Iterator::filter_map`."##, + }, Lint { label: "clippy::filter_map_identity", description: r##"Checks for usage of `filter_map(|x| x)`."##, @@ -5162,7 +10628,7 @@ with Default::default()."##, }, Lint { label: "clippy::flat_map_option", - description: r##"Checks for usages of `Iterator::flat_map()` where `filter_map()` could be + description: r##"Checks for usage of `Iterator::flat_map()` where `filter_map()` could be used instead."##, }, Lint { label: "clippy::float_arithmetic", description: r##"Checks for float arithmetic."## }, @@ -5211,18 +10677,12 @@ store address."##, ignoring either the keys or values."##, }, Lint { - label: "clippy::for_loops_over_fallibles", - description: r##"Checks for `for` loops over `Option` or `Result` values."##, + 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::()`."##, }, Lint { label: "clippy::format_in_format_args", @@ -5230,6 +10690,15 @@ instead of an owned value."##, formatting such as `format!` itself, `write!` or `println!`. Suggests inlining the `format!` call."##, }, + Lint { + label: "clippy::format_push_string", + description: r##"Detects cases where the result of a `format!` call is +appended to an existing `String`."##, + }, + Lint { + label: "clippy::four_forward_slashes", + description: r##"Checks for outer doc comments written with 4 forward slashes (`////`)."##, + }, Lint { label: "clippy::from_iter_instead_of_collect", description: r##"Checks for `from_iter()` function calls on types that implement the `FromIterator` @@ -5239,6 +10708,10 @@ trait."##, label: "clippy::from_over_into", description: r##"Searches for implementations of the `Into<..>` trait and suggests to implement `From<..>` instead."##, }, + Lint { + label: "clippy::from_raw_with_void_ptr", + description: r##"Checks if we're passing a `c_void` raw pointer to `{Box,Rc,Arc,Weak}::from_raw(_)`"##, + }, Lint { label: "clippy::from_str_radix_10", description: r##"Checks for function invocations of the form `primitive::from_str_radix(s, 10)`"##, @@ -5249,17 +10722,26 @@ trait."##, functions and methods to implement the `Send` marker trait. It is mostly used by library authors (public and internal) that target an audience where multithreaded executors are likely to be used for running these Futures."##, + }, + Lint { + label: "clippy::get_first", + description: r##"Checks for usage of `x.get(0)` instead of +`x.first()`."##, }, Lint { label: "clippy::get_last_with_len", - description: r##"Checks for using `x.get(x.len() - 1)` instead of + description: r##"Checks for usage of `x.get(x.len() - 1)` instead of `x.last()`."##, }, Lint { label: "clippy::get_unwrap", - description: r##"Checks for use of `.get().unwrap()` (or + description: r##"Checks for usage of `.get().unwrap()` (or `.get_mut().unwrap`) on a standard library type which implements `Index`"##, }, + Lint { + label: "clippy::host_endian_bytes", + description: r##"Checks for the usage of the `to_ne_bytes` method and/or the function `from_ne_bytes`."##, + }, Lint { label: "clippy::identity_op", description: r##"Checks for identity operations, e.g., `x + 0`."##, @@ -5285,12 +10767,20 @@ and the *else* part."##, }, Lint { label: "clippy::if_then_some_else_none", - description: r##"Checks for if-else that could be written to `bool::then`."##, + description: r##"Checks for if-else that could be written using either `bool::then` or `bool::then_some`."##, }, Lint { label: "clippy::ifs_same_cond", description: r##"Checks for consecutive `if`s with the same condition."##, }, + Lint { + label: "clippy::ignored_unit_patterns", + description: r##"Checks for usage of `_` in patterns of type `()`."##, + }, + Lint { + label: "clippy::impl_trait_in_params", + description: r##"Lints when `impl Trait` is being used in a function's parameters."##, + }, Lint { label: "clippy::implicit_clone", description: r##"Checks for the usage of `_.to_owned()`, `vec.to_vec()`, or similar when calling `_.clone()` would be clearer."##, @@ -5305,10 +10795,25 @@ algorithm (`SipHash`)."##, label: "clippy::implicit_return", description: r##"Checks for missing return statements at the end of a block."##, }, + Lint { + label: "clippy::implicit_saturating_add", + description: r##"Checks for implicit saturating addition."##, + }, Lint { label: "clippy::implicit_saturating_sub", description: r##"Checks for implicit saturating subtraction."##, }, + Lint { + label: "clippy::implied_bounds_in_impls", + description: r##"Looks for bounds in `impl Trait` in return position that are implied by other bounds. +This can happen when a trait is specified that another trait already has as a supertrait +(e.g. `fn() -> impl Deref + DerefMut` has an unnecessary `Deref` bound, +because `Deref` is a supertrait of `DerefMut`)"##, + }, + Lint { + label: "clippy::impossible_comparisons", + description: r##"Checks for double comparisons that can never succeed"##, + }, Lint { label: "clippy::imprecise_flops", description: r##"Looks for floating-point expressions that @@ -5343,10 +10848,10 @@ lint on constant `usize` indexing on arrays because that is handled by rustc's ` without changing the outcome. The basic structure can be seen in the following table: -|Comparison| Bit Op |Example |equals | -|----------|---------|-----------|-------| -|`>` / `<=`|`|` / `^`|`x | 2 > 3`|`x > 3`| -|`<` / `>=`|`|` / `^`|`x ^ 1 < 4`|`x < 4`|"##, +|Comparison| Bit Op |Example |equals | +|----------|----------|------------|-------| +|`>` / `<=`|`\\|` / `^`|`x \\| 2 > 3`|`x > 3`| +|`<` / `>=`|`\\|` / `^`|`x ^ 1 < 4` |`x < 4`|"##, }, Lint { label: "clippy::inefficient_to_string", @@ -5370,6 +10875,12 @@ or tuple struct where a `let` will suffice."##, label: "clippy::inherent_to_string_shadow_display", description: r##"Checks for the definition of inherent methods with a signature of `to_string(&self) -> String` and if the type implementing this method also implements the `Display` trait."##, }, + Lint { + label: "clippy::init_numbered_fields", + description: r##"Checks for tuple structs initialized with field syntax. +It will however not lint if a base initializer is present. +The lint will also ignore code in macros."##, + }, Lint { label: "clippy::inline_always", description: r##"Checks for items annotated with `#[inline(always)]`, @@ -5395,21 +10906,17 @@ unless the annotated function is empty or simply panics."##, label: "clippy::int_plus_one", description: r##"Checks for usage of `x >= y + 1` or `x - 1 >= y` (and `<=`) in a block"##, }, - Lint { - label: "clippy::integer_arithmetic", - description: r##"Checks for integer arithmetic operations which could overflow or panic. - -Specifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable -of overflowing according to the [Rust -Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow), -or which can panic (`/`, `%`). No bounds analysis or sophisticated reasoning is -attempted."##, - }, Lint { label: "clippy::integer_division", description: r##"Checks for division of integers"## }, Lint { label: "clippy::into_iter_on_ref", description: r##"Checks for `into_iter` calls on references which should be replaced by `iter` or `iter_mut`."##, + }, + Lint { + label: "clippy::into_iter_without_iter", + description: r##"This is the opposite of the `iter_without_into_iter` lint. +It looks for `IntoIterator for (&|&mut) Type` implementations without an inherent `iter` or `iter_mut` method +on the type or on any of the types in its `Deref` chain."##, }, Lint { label: "clippy::invalid_null_ptr_usage", @@ -5431,10 +10938,20 @@ necessary. Only integer types are checked."##, label: "clippy::invisible_characters", description: r##"Checks for invisible Unicode characters in the code."##, }, + Lint { + label: "clippy::is_digit_ascii_radix", + description: r##"Finds usages of [`char::is_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_digit) that +can be replaced with [`is_ascii_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_ascii_digit) or +[`is_ascii_hexdigit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_ascii_hexdigit)."##, + }, Lint { label: "clippy::items_after_statements", description: r##"Checks for items declared after some statement in a block."##, }, + Lint { + label: "clippy::items_after_test_module", + description: r##"Triggers if an item is declared after the testing module marked with `#[cfg(test)]`."##, + }, Lint { label: "clippy::iter_cloned_collect", description: r##"Checks for the use of `.cloned().collect()` on slice to @@ -5444,6 +10961,11 @@ create a `Vec`."##, label: "clippy::iter_count", description: r##"Checks for the use of `.iter().count()`."##, }, + Lint { + label: "clippy::iter_kv_map", + description: r##"Checks for iterating a map (`HashMap` or `BTreeMap`) and +ignoring either the keys or values."##, + }, Lint { label: "clippy::iter_next_loop", description: r##"Checks for loops on `x.next()`."## }, Lint { label: "clippy::iter_next_slice", @@ -5455,16 +10977,45 @@ create a `Vec`."##, }, Lint { label: "clippy::iter_nth", - description: r##"Checks for use of `.iter().nth()` (and the related + description: r##"Checks for usage of `.iter().nth()` (and the related `.iter_mut().nth()`) on standard library types with *O*(1) element access."##, }, Lint { label: "clippy::iter_nth_zero", description: r##"Checks for the use of `iter.nth(0)`."##, }, + Lint { + label: "clippy::iter_on_empty_collections", + description: r##"Checks for calls to `iter`, `iter_mut` or `into_iter` on empty collections"##, + }, + Lint { + label: "clippy::iter_on_single_items", + description: r##"Checks for calls to `iter`, `iter_mut` or `into_iter` on collections containing a single item"##, + }, + Lint { + label: "clippy::iter_out_of_bounds", + description: r##"Looks for iterator combinator calls such as `.take(x)` or `.skip(x)` +where `x` is greater than the amount of items that an iterator will produce."##, + }, + Lint { + label: "clippy::iter_overeager_cloned", + description: r##"Checks for usage of `_.cloned().()` where call to `.cloned()` can be postponed."##, + }, Lint { label: "clippy::iter_skip_next", - description: r##"Checks for use of `.skip(x).next()` on iterators."##, + description: r##"Checks for usage of `.skip(x).next()` on iterators."##, + }, + Lint { + label: "clippy::iter_skip_zero", + description: r##"Checks for usage of `.skip(0)` on iterators."##, + }, + Lint { + label: "clippy::iter_with_drain", + description: r##"Checks for usage of `.drain(..)` on `Vec` and `VecDeque` for iteration."##, + }, + Lint { + label: "clippy::iter_without_into_iter", + description: r##"Looks for `iter` and `iter_mut` methods without an associated `IntoIterator for (&|&mut) Type` implementation."##, }, Lint { label: "clippy::iterator_step_by_zero", @@ -5490,11 +11041,30 @@ are too large."##, label: "clippy::large_enum_variant", description: r##"Checks for large size differences between variants on `enum`s."##, + }, + Lint { + label: "clippy::large_futures", + description: r##"It checks for the size of a `Future` created by `async fn` or `async {}`."##, + }, + Lint { + label: "clippy::large_include_file", + description: r##"Checks for the inclusion of large files via `include_bytes!()` +and `include_str!()`"##, }, Lint { label: "clippy::large_stack_arrays", description: r##"Checks for local arrays that may be too large."##, }, + Lint { + label: "clippy::large_stack_frames", + description: r##"Checks for functions that use a lot of stack space. + +This often happens when constructing a large type, such as an array with a lot of elements, +or constructing *many* smaller-but-still-large structs, or copying around a lot of large types. + +This lint is a more general version of [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/#large_stack_arrays) +that is intended to look at functions as a whole instead of only individual array expressions inside of a function."##, + }, Lint { label: "clippy::large_types_passed_by_value", description: r##"Checks for functions taking arguments by value, where @@ -5519,29 +11089,42 @@ just to compare to zero, and suggests using `.is_empty()` where applicable."##, returned."##, }, Lint { - label: "clippy::let_underscore_drop", - description: r##"Checks for `let _ = ` -where expr has a type that implements `Drop`"##, + label: "clippy::let_underscore_future", + description: r##"Checks for `let _ = ` where the resulting type of expr implements `Future`"##, }, Lint { label: "clippy::let_underscore_lock", - description: r##"Checks for `let _ = sync_lock`. -This supports `mutex` and `rwlock` in `std::sync` and `parking_lot`."##, + description: r##"Checks for `let _ = sync_lock`. This supports `mutex` and `rwlock` in +`parking_lot`. For `std` locks see the `rustc` lint +[`let_underscore_lock`](https://doc.rust-lang.org/nightly/rustc/lints/listing/deny-by-default.html#let-underscore-lock)"##, }, Lint { label: "clippy::let_underscore_must_use", description: r##"Checks for `let _ = ` where expr is `#[must_use]`"##, }, + Lint { + label: "clippy::let_underscore_untyped", + description: r##"Checks for `let _ = ` without a type annotation, and suggests to either provide one, +or remove the `let` keyword altogether."##, + }, Lint { label: "clippy::let_unit_value", description: r##"Checks for binding a unit value."## }, + Lint { + label: "clippy::let_with_type_underscore", + description: r##"Detects when a variable is declared with an explicit type of `_`."##, + }, + Lint { + label: "clippy::lines_filter_map_ok", + description: r##"Checks for usage of `lines.filter_map(Result::ok)` or `lines.flat_map(Result::ok)` +when `lines` has type `std::io::Lines`."##, + }, Lint { label: "clippy::linkedlist", description: r##"Checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`)."##, }, Lint { - label: "clippy::logic_bug", - description: r##"Checks for boolean expressions that contain terminals that -can be eliminated."##, + label: "clippy::little_endian_bytes", + description: r##"Checks for the usage of the `to_le_bytes` method and/or the function `from_le_bytes`."##, }, Lint { label: "clippy::lossy_float_literal", @@ -5564,11 +11147,28 @@ cannot be represented as the underlying type without loss."##, label: "clippy::manual_async_fn", description: r##"It checks for manual implementations of `async` functions."##, }, + Lint { + label: "clippy::manual_bits", + description: r##"Checks for usage of `std::mem::size_of::() * 8` when +`T::BITS` is available."##, + }, + Lint { + label: "clippy::manual_clamp", + description: r##"Identifies good opportunities for a clamp function from std or core, and suggests using it."##, + }, + Lint { + label: "clippy::manual_filter", + description: r##"Checks for usage of `match` which could be implemented using `filter`"##, + }, Lint { label: "clippy::manual_filter_map", description: r##"Checks for usage of `_.filter(_).map(_)` that can be written more simply as `filter_map(_)`."##, }, + Lint { + label: "clippy::manual_find", + description: r##"Checks for manual implementations of Iterator::find"##, + }, Lint { label: "clippy::manual_find_map", description: r##"Checks for usage of `_.find(_).map(_)` that can be written more simply @@ -5576,18 +11176,56 @@ as `find_map(_)`."##, }, Lint { label: "clippy::manual_flatten", - description: r##"Check for unnecessary `if let` usage in a for loop + description: r##"Checks for unnecessary `if let` usage in a for loop where only the `Some` or `Ok` variant of the iterator element is used."##, + }, + Lint { + label: "clippy::manual_hash_one", + description: r##"Checks for cases where [`BuildHasher::hash_one`] can be used. + +[`BuildHasher::hash_one`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html#method.hash_one"##, + }, + Lint { + label: "clippy::manual_instant_elapsed", + description: r##"Lints subtraction between `Instant::now()` and another `Instant`."##, + }, + Lint { + label: "clippy::manual_is_ascii_check", + description: r##"Suggests to use dedicated built-in methods, +`is_ascii_(lowercase|uppercase|digit)` for checking on corresponding ascii range"##, + }, + Lint { + label: "clippy::manual_is_finite", + description: r##"Checks for manual `is_finite` reimplementations +(i.e., `x != ::INFINITY && x != ::NEG_INFINITY`)."##, + }, + Lint { + label: "clippy::manual_is_infinite", + description: r##"Checks for manual `is_infinite` reimplementations +(i.e., `x == ::INFINITY || x == ::NEG_INFINITY`)."##, + }, + Lint { + label: "clippy::manual_let_else", + description: r##"Warn of cases where `let...else` could be used"##, + }, + Lint { + label: "clippy::manual_main_separator_str", + description: r##"Checks for references on `std::path::MAIN_SEPARATOR.to_string()` used +to build a `&str`."##, }, Lint { label: "clippy::manual_map", - description: r##"Checks for usages of `match` which could be implemented using `map`"##, + description: r##"Checks for usage of `match` which could be implemented using `map`"##, }, Lint { label: "clippy::manual_memcpy", description: r##"Checks for for-loops that manually copy items between slices that could be optimized by having a memcpy."##, }, + Lint { + label: "clippy::manual_next_back", + description: r##"Checks for `.rev().next()` on a `DoubleEndedIterator`"##, + }, Lint { label: "clippy::manual_non_exhaustive", description: r##"Checks for manual implementations of the non-exhaustive pattern."##, @@ -5601,28 +11239,66 @@ slices that could be optimized by having a memcpy."##, description: r##"Checks for expressions like `x >= 3 && x < 8` that could be more readably expressed as `(3..8).contains(x)`."##, }, + Lint { + label: "clippy::manual_range_patterns", + description: r##"Looks for combined OR patterns that are all contained in a specific range, +e.g. `6 | 4 | 5 | 9 | 7 | 8` can be rewritten as `4..=9`."##, + }, + Lint { + label: "clippy::manual_rem_euclid", + description: r##"Checks for an expression like `((x % 4) + 4) % 4` which is a common manual reimplementation +of `x.rem_euclid(4)`."##, + }, + Lint { + label: "clippy::manual_retain", + description: r##"Checks for code to be replaced by `.retain()`."##, + }, Lint { label: "clippy::manual_saturating_arithmetic", description: r##"Checks for `.checked_add/sub(x).unwrap_or(MAX/MIN)`."##, }, + Lint { + label: "clippy::manual_slice_size_calculation", + description: r##"When `a` is `&[T]`, detect `a.len() * size_of::()` and suggest `size_of_val(a)` +instead."##, + }, Lint { label: "clippy::manual_split_once", - description: r##"Checks for usages of `str::splitn(2, _)`"##, + description: r##"Checks for usage of `str::splitn(2, _)`"##, }, Lint { label: "clippy::manual_str_repeat", description: r##"Checks for manual implementations of `str::repeat`"##, }, + Lint { + label: "clippy::manual_string_new", + description: r##"Checks for usage of `` to create a `String`, such as `.to_string()`, `.to_owned()`, +`String::from()` and others."##, + }, Lint { label: "clippy::manual_strip", description: r##"Suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing using the pattern's length."##, }, - Lint { label: "clippy::manual_swap", description: r##"Checks for manual swapping."## }, + Lint { + label: "clippy::manual_swap", + description: r##"Checks for manual swapping. + +Note that the lint will not be emitted in const blocks, as the suggestion would not be applicable."##, + }, + Lint { + label: "clippy::manual_try_fold", + description: r##"Checks for usage of `Iterator::fold` with a type that implements `Try`."##, + }, Lint { label: "clippy::manual_unwrap_or", description: r##"Finds patterns that reimplement `Option::unwrap_or` or `Result::unwrap_or`."##, }, + Lint { + label: "clippy::manual_while_let_some", + description: r##"Looks for loops that check for emptiness of a `Vec` in the condition and pop an element +in the body as a separate operation."##, + }, Lint { label: "clippy::many_single_char_names", description: r##"Checks for too many variables whose name consists of a @@ -5640,7 +11316,7 @@ and suggests `cloned()` or `copied()` instead"##, }, Lint { label: "clippy::map_entry", - description: r##"Checks for uses of `contains_key` + `insert` on `HashMap` + description: r##"Checks for usage of `contains_key` + `insert` on `HashMap` or `BTreeMap`."##, }, Lint { @@ -5695,7 +11371,10 @@ instead. It also checks for `if let &foo = bar` blocks."##, }, Lint { label: "clippy::match_same_arms", - description: r##"Checks for `match` with identical arm bodies."##, + description: r##"Checks for `match` with identical arm bodies. + +Note: Does not lint on wildcards if the `non_exhaustive_omitted_patterns_lint` feature is +enabled and disallowed."##, }, Lint { label: "clippy::match_single_binding", @@ -5718,10 +11397,15 @@ and take drastic actions like `panic!`."##, label: "clippy::maybe_infinite_iter", description: r##"Checks for iteration that may be infinite."##, }, + Lint { + label: "clippy::maybe_misused_cfg", + description: r##"Checks for `#[cfg(features = ...)]` and suggests to replace it with +`#[cfg(feature = ...)]`."##, + }, Lint { label: "clippy::mem_forget", description: r##"Checks for usage of `std::mem::forget(t)` where `t` is -`Drop`."##, +`Drop` or has a field that implements `Drop`."##, }, Lint { label: "clippy::mem_replace_option_with_none", @@ -5737,6 +11421,13 @@ and take drastic actions like `panic!`."##, label: "clippy::mem_replace_with_uninit", description: r##"Checks for `mem::replace(&mut _, mem::uninitialized())` and `mem::replace(&mut _, mem::zeroed())`."##, + }, + Lint { + label: "clippy::min_ident_chars", + description: r##"Checks for idents which comprise of a single letter. + +Note: This lint can be very noisy when enabled; it may be desirable to only enable it +temporarily."##, }, Lint { label: "clippy::min_max", @@ -5751,18 +11442,38 @@ used to clamp values, but switched so that the result is constant."##, label: "clippy::mismatched_target_os", description: r##"Checks for cfg attributes having operating systems used in target family position."##, }, + Lint { + label: "clippy::mismatching_type_param_order", + description: r##"Checks for type parameters which are positioned inconsistently between +a type definition and impl block. Specifically, a parameter in an impl +block which has the same name as a parameter in the type def, but is in +a different place."##, + }, + Lint { + label: "clippy::misnamed_getters", + description: r##"Checks for getter methods that return a field that doesn't correspond +to the name of the method, when there is a field's whose name matches that of the method."##, + }, Lint { label: "clippy::misrefactored_assign_op", description: r##"Checks for `a op= a op b` or `a op= b op a` patterns."##, }, + Lint { + label: "clippy::missing_assert_message", + description: r##"Checks assertions without a custom panic message."##, + }, + Lint { + label: "clippy::missing_asserts_for_indexing", + description: r##"Checks for repeated slice indexing without asserting beforehand that the length +is greater than the largest index used to index into the slice."##, + }, Lint { label: "clippy::missing_const_for_fn", description: r##"Suggests the use of `const` in functions and methods where possible."##, }, Lint { label: "clippy::missing_docs_in_private_items", - description: r##"Warns if there is missing doc for any documentable item -(public or private)."##, + description: r##"Warns if there is missing doc for any private documentable item"##, }, Lint { label: "clippy::missing_enforced_import_renames", @@ -5774,6 +11485,10 @@ in the `enforce-import-renames` config option."##, description: r##"Checks the doc comments of publicly visible functions that return a `Result` type and warns if there is no `# Errors` section."##, }, + Lint { + label: "clippy::missing_fields_in_debug", + description: r##"Checks for manual [`core::fmt::Debug`](https://doc.rust-lang.org/core/fmt/trait.Debug.html) implementations that do not use all fields."##, + }, Lint { label: "clippy::missing_inline_in_public_items", description: r##"It lints if an exported function, method, trait method with default impl, @@ -5788,6 +11503,17 @@ may panic and warns if there is no `# Panics` section."##, label: "clippy::missing_safety_doc", description: r##"Checks for the doc comments of publicly visible unsafe functions and warns if there is no `# Safety` section."##, + }, + Lint { label: "clippy::missing_spin_loop", description: r##"Checks for empty spin loops"## }, + Lint { + label: "clippy::missing_trait_methods", + description: r##"Checks if a provided method is used implicitly by a trait +implementation. A usage example would be a wrapper where every method +should perform some operation before delegating to the inner type's +implementation. + +This lint should typically be enabled on a specific trait `impl` item +rather than globally."##, }, Lint { label: "clippy::mistyped_literal_suffixes", @@ -5797,10 +11523,16 @@ unsafe functions and warns if there is no `# Safety` section."##, label: "clippy::mixed_case_hex_literals", description: r##"Warns on hexadecimal literals with mixed-case letter digits."##, + }, + Lint { + label: "clippy::mixed_read_write_in_expression", + description: r##"Checks for a read and a write to the same variable where +whether the read occurs before or after the write depends on the evaluation +order of sub-expressions."##, }, Lint { label: "clippy::mod_module_files", - description: r##"Checks that module layout uses only self named module files, bans mod.rs files."##, + description: r##"Checks that module layout uses only self named module files, bans `mod.rs` files."##, }, Lint { label: "clippy::module_inception", @@ -5818,6 +11550,7 @@ containing module's name."##, description: r##"Checks for getting the remainder of a division by one or minus one."##, }, + Lint { label: "clippy::multi_assignments", description: r##"Checks for nested assignments."## }, Lint { label: "clippy::multiple_crate_versions", description: r##"Checks to see if multiple versions of a crate are being @@ -5827,6 +11560,10 @@ used."##, label: "clippy::multiple_inherent_impl", description: r##"Checks for multiple inherent implementations of a struct"##, }, + Lint { + label: "clippy::multiple_unsafe_ops_per_block", + description: r##"Checks for `unsafe` blocks that contain more than one unsafe operation."##, + }, Lint { label: "clippy::must_use_candidate", description: r##"Checks for public functions that have no @@ -5840,8 +11577,12 @@ unit-returning functions and methods."##, }, Lint { label: "clippy::mut_from_ref", - description: r##"This lint checks for functions that take immutable -references and return mutable ones."##, + description: r##"This lint checks for functions that take immutable references and return +mutable ones. This will not trigger if no unsafe code exists as there +are multiple safe functions which will do this transformation + +To be on the conservative side, if there's at least one mutable +reference with the output lifetime, this lint will not trigger."##, }, Lint { label: "clippy::mut_mut", @@ -5861,11 +11602,11 @@ references and return mutable ones."##, }, Lint { label: "clippy::mutex_atomic", - description: r##"Checks for usages of `Mutex` where an atomic will do."##, + description: r##"Checks for usage of `Mutex` where an atomic will do."##, }, Lint { label: "clippy::mutex_integer", - description: r##"Checks for usages of `Mutex` where `X` is an integral + description: r##"Checks for usage of `Mutex` where `X` is an integral type."##, }, Lint { label: "clippy::naive_bytecount", description: r##"Checks for naive byte counts"## }, @@ -5876,13 +11617,19 @@ specify the `Self`-type explicitly"##, }, Lint { label: "clippy::needless_bitwise_bool", - description: r##"Checks for uses of bitwise and/or operators between booleans, where performance may be improved by using + description: r##"Checks for usage of bitwise and/or operators between booleans, where performance may be improved by using a lazy and."##, }, Lint { label: "clippy::needless_bool", description: r##"Checks for expressions of the form `if c { true } else { false }` (or vice versa) and suggests using the condition directly."##, + }, + Lint { + label: "clippy::needless_bool_assign", + description: r##"Checks for expressions of the form `if c { x = true } else { x = false }` +(or vice versa) and suggest assigning the variable directly from the +condition."##, }, Lint { label: "clippy::needless_borrow", @@ -5891,8 +11638,13 @@ be dereferenced immediately by the compiler."##, }, Lint { label: "clippy::needless_borrowed_reference", - description: r##"Checks for bindings that destructure a reference and borrow the inner + description: r##"Checks for bindings that needlessly destructure a reference and borrow the inner value with `&ref`."##, + }, + Lint { + label: "clippy::needless_borrows_for_generic_args", + description: r##"Checks for borrow operations (`&`) that used as a generic argument to a +function when the borrowed value could be used."##, }, Lint { label: "clippy::needless_collect", @@ -5910,11 +11662,16 @@ rearrangement of code can make the code easier to understand."##, label: "clippy::needless_doctest_main", description: r##"Checks for `fn main() { .. }` in doctests"##, }, + Lint { label: "clippy::needless_else", description: r##"Checks for empty `else` branches."## }, Lint { label: "clippy::needless_for_each", description: r##"Checks for usage of `for_each` that would be more simply written as a `for` loop."##, }, + Lint { + label: "clippy::needless_if", + description: r##"Checks for empty `if` branches with no else branch."##, + }, Lint { label: "clippy::needless_late_init", description: r##"Checks for late initializations that can be replaced by a `let` statement @@ -5924,11 +11681,32 @@ with an initializer."##, label: "clippy::needless_lifetimes", description: r##"Checks for lifetime annotations which can be removed by relying on lifetime elision."##, + }, + Lint { + label: "clippy::needless_match", + description: r##"Checks for unnecessary `match` or match-like `if let` returns for `Option` and `Result` +when function signatures are the same."##, }, Lint { label: "clippy::needless_option_as_deref", - description: r##"Checks for no-op uses of Option::{as_deref,as_deref_mut}, + description: r##"Checks for no-op uses of `Option::{as_deref, as_deref_mut}`, for example, `Option<&T>::as_deref()` returns the same type."##, + }, + Lint { + label: "clippy::needless_option_take", + description: r##"Checks for calling `take` function after `as_ref`."##, + }, + Lint { + label: "clippy::needless_parens_on_range_literals", + description: r##"The lint checks for parenthesis on literals in range statements that are +superfluous."##, + }, + Lint { + label: "clippy::needless_pass_by_ref_mut", + description: r##"Check if a `&mut` function argument is actually used mutably. + +Be careful if the function is publicly reexported as it would break compatibility with +users of this function."##, }, Lint { label: "clippy::needless_pass_by_value", @@ -5936,6 +11714,10 @@ for example, `Option<&T>::as_deref()` returns the same type."##, consuming them in its body."##, }, + Lint { + label: "clippy::needless_pub_self", + description: r##"Checks for usage of `pub(self)` and `pub(in self)`."##, + }, Lint { label: "clippy::needless_question_mark", description: r##"Suggests alternatives for useless applications of `?` in terminating expressions"##, @@ -5945,13 +11727,25 @@ body."##, description: r##"Checks for looping over the range of `0..len` of some collection just to get the values by index."##, }, + Lint { + label: "clippy::needless_raw_string_hashes", + description: r##"Checks for raw string literals with an unnecessary amount of hashes around them."##, + }, + Lint { + label: "clippy::needless_raw_strings", + description: r##"Checks for raw string literals where a string literal can be used instead."##, + }, Lint { label: "clippy::needless_return", description: r##"Checks for return statements at the end of a block."##, }, + Lint { + label: "clippy::needless_return_with_question_mark", + description: r##"Checks for return statements on `Err` paired with the `?` operator."##, + }, Lint { label: "clippy::needless_splitn", - description: r##"Checks for usages of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same."##, + description: r##"Checks for usage of `str::splitn` (or `str::rsplitn`) where using `str::split` would be the same."##, }, Lint { label: "clippy::needless_update", @@ -5985,7 +11779,7 @@ This lint is not applied to structs marked with }, Lint { label: "clippy::new_without_default", - description: r##"Checks for types with a `fn new() -> Self` method and no + description: r##"Checks for public types with a `pub fn new() -> Self` method and no implementation of [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)."##, }, @@ -5993,14 +11787,34 @@ implementation of label: "clippy::no_effect", description: r##"Checks for statements which have no effect."##, }, + Lint { + label: "clippy::no_effect_replace", + description: r##"Checks for `replace` statements which have no effect."##, + }, Lint { label: "clippy::no_effect_underscore_binding", description: r##"Checks for binding to underscore prefixed variable without side-effects."##, }, + Lint { + label: "clippy::no_mangle_with_rust_abi", + description: r##"Checks for Rust ABI functions with the `#[no_mangle]` attribute."##, + }, Lint { label: "clippy::non_ascii_literal", description: r##"Checks for non-ASCII characters in string and char literals."##, }, + Lint { + label: "clippy::non_canonical_clone_impl", + description: r##"Checks for non-canonical implementations of `Clone` when `Copy` is already implemented."##, + }, + Lint { + label: "clippy::non_canonical_partial_ord_impl", + description: r##"Checks for non-canonical implementations of `PartialOrd` when `Ord` is already implemented."##, + }, + Lint { + label: "clippy::non_minimal_cfg", + description: r##"Checks for `any` and `all` combinators in `cfg` with only one condition."##, + }, Lint { label: "clippy::non_octal_unix_permissions", description: r##"Checks for non-octal values used to set Unix file permissions."##, @@ -6032,12 +11846,20 @@ that make no sense."##, description: r##"Checks for public functions that dereference raw pointer arguments but are not marked `unsafe`."##, }, + Lint { + label: "clippy::obfuscated_if_else", + description: r##"Checks for usage of `.then_some(..).unwrap_or(..)`"##, + }, Lint { label: "clippy::octal_escapes", description: r##"Checks for `\\0` escapes in string and byte literals that look like octal character escapes in C."##, }, Lint { label: "clippy::ok_expect", description: r##"Checks for usage of `ok().expect(..)`."## }, + Lint { + label: "clippy::only_used_in_recursion", + description: r##"Checks for arguments that are only used in recursion with no side-effects."##, + }, Lint { label: "clippy::op_ref", description: r##"Checks for arguments to `==` which have their address @@ -6046,7 +11868,7 @@ and suggests to dereference the other argument instead"##, }, Lint { label: "clippy::option_as_ref_deref", - description: r##"Checks for usage of `_.as_ref().map(Deref::deref)` or it's aliases (such as String::as_str)."##, + description: r##"Checks for usage of `_.as_ref().map(Deref::deref)` or its aliases (such as String::as_str)."##, }, Lint { label: "clippy::option_env_unwrap", @@ -6059,7 +11881,8 @@ suggests usage of the `env!` macro."##, }, Lint { label: "clippy::option_if_let_else", - description: r##"Lints usage of `if let Some(v) = ... { y } else { x }` which is more + description: r##"Lints usage of `if let Some(v) = ... { y } else { x }` and +`match .. { Some(v) => y, None/_ => x }` which are more idiomatically done with `Option::map_or` (if the else bit is a pure expression) or `Option::map_or_else` (if the else bit is an impure expression)."##, @@ -6075,14 +11898,19 @@ or closure that returns the unit type `()`."##, }, Lint { label: "clippy::option_option", - description: r##"Checks for use of `Option>` in function signatures and type + description: r##"Checks for usage of `Option>` in function signatures and type definitions"##, }, Lint { label: "clippy::or_fun_call", description: r##"Checks for calls to `.or(foo(..))`, `.unwrap_or(foo(..))`, -etc., and suggests to use `or_else`, `unwrap_or_else`, etc., or -`unwrap_or_default` instead."##, +`.or_insert(foo(..))` etc., and suggests to use `.or_else(|| foo(..))`, +`.unwrap_or_else(|| foo(..))`, `.unwrap_or_default()` or `.or_default()` +etc. instead."##, + }, + Lint { + label: "clippy::or_then_unwrap", + description: r##"Checks for `.or(…).unwrap()` calls to Options and Results."##, }, Lint { label: "clippy::out_of_bounds_indexing", @@ -6093,23 +11921,47 @@ index."##, label: "clippy::overflow_check_conditional", description: r##"Detects classic underflow/overflow checks."##, }, + Lint { + label: "clippy::overly_complex_bool_expr", + description: r##"Checks for boolean expressions that contain terminals that +can be eliminated."##, + }, Lint { label: "clippy::panic", description: r##"Checks for usage of `panic!`."## }, Lint { label: "clippy::panic_in_result_fn", - description: r##"Checks for usage of `panic!`, `unimplemented!`, `todo!`, `unreachable!` or assertions in a function of type result."##, + description: r##"Checks for usage of `panic!` or assertions in a function of type result."##, }, Lint { label: "clippy::panicking_unwrap", description: r##"Checks for calls of `unwrap[_err]()` that will always fail."##, }, + Lint { + label: "clippy::partial_pub_fields", + description: r##"Checks whether partial fields of a struct are public. + +Either make all fields of a type public, or make none of them public"##, + }, Lint { label: "clippy::partialeq_ne_impl", description: r##"Checks for manual re-implementations of `PartialEq::ne`."##, }, + Lint { + label: "clippy::partialeq_to_none", + description: r##"Checks for binary comparisons to a literal `Option::None`."##, + }, Lint { label: "clippy::path_buf_push_overwrite", description: r##"* Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push) calls on `PathBuf` that can cause overwrites."##, + }, + Lint { + label: "clippy::path_ends_with_ext", + description: r##"Looks for calls to `Path::ends_with` calls where the argument looks like a file extension. + +By default, Clippy has a short list of known filenames that start with a dot +but aren't necessarily file extensions (e.g. the `.git` folder), which are allowed by default. +The `allowed-dotfiles` configuration can be used to allow additional +file extensions that Clippy should not lint."##, }, Lint { label: "clippy::pattern_type_mismatch", @@ -6132,6 +11984,10 @@ in a general way even outside of the various pattern matching mechanics. Of cour this lint can still be used to highlight areas of interest and ensure a good understanding of ownership semantics."##, }, + Lint { + label: "clippy::permissions_set_readonly_false", + description: r##"Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`."##, + }, Lint { label: "clippy::possible_missing_comma", description: r##"Checks for possible missing comma in an array. It lints if @@ -6146,6 +12002,11 @@ parentheses * a negative numeric literal (which is really a unary `-` followed by a numeric literal) followed by a method call"##, + }, + Lint { + label: "clippy::print_in_format_impl", + description: r##"Checks for usage of `println`, `print`, `eprintln` or `eprint` in an +implementation of a formatting trait."##, }, Lint { label: "clippy::print_literal", @@ -6173,15 +12034,19 @@ print a newline."##, }, Lint { label: "clippy::ptr_arg", - description: r##"This lint checks for function arguments of type `&String` -or `&Vec` unless the references are mutable. It will also suggest you -replace `.clone()` calls with the appropriate `.to_owned()`/`to_string()` -calls."##, + description: r##"This lint checks for function arguments of type `&String`, `&Vec`, +`&PathBuf`, and `Cow<_>`. It will also suggest you replace `.clone()` calls +with the appropriate `.to_owned()`/`to_string()` calls."##, }, Lint { label: "clippy::ptr_as_ptr", description: r##"Checks for `as` casts between raw pointers without changing its mutability, namely `*const T` to `*const U` and `*mut T` to `*mut U`."##, + }, + Lint { + label: "clippy::ptr_cast_constness", + description: r##"Checks for `as` casts between raw pointers which change its constness, namely `*const T` to +`*mut T` and `*mut T` to `*const T`."##, }, Lint { label: "clippy::ptr_eq", description: r##"Use `std::ptr::eq` when applicable"## }, Lint { @@ -6193,10 +12058,26 @@ namely `*const T` to `*const U` and `*mut T` to `*mut U`."##, label: "clippy::pub_enum_variant_names", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { label: "clippy::pub_use", description: r##"Restricts the usage of `pub use ...`"## }, + Lint { + label: "clippy::pub_with_shorthand", + description: r##"Checks for usage of `pub()` with `in`."##, + }, + Lint { + label: "clippy::pub_without_shorthand", + description: r##"Checks for usage of `pub()` without `in`. + +Note: As you cannot write a module's path in `pub()`, this will only trigger on +`pub(super)` and the like."##, + }, Lint { label: "clippy::question_mark", description: r##"Checks for expressions that could be replaced by the question mark operator."##, }, + Lint { + label: "clippy::question_mark_used", + description: r##"Checks for expressions that use the question mark operator and rejects them."##, + }, Lint { label: "clippy::range_minus_one", description: r##"Checks for inclusive ranges where 1 is subtracted from @@ -6220,10 +12101,49 @@ upper bound, e.g., `x..(y+1)`."##, label: "clippy::rc_buffer", description: r##"Checks for `Rc` and `Arc` when `T` is a mutable buffer type such as `String` or `Vec`."##, }, + Lint { + label: "clippy::rc_clone_in_vec_init", + description: r##"Checks for reference-counted pointers (`Arc`, `Rc`, `rc::Weak`, and `sync::Weak`) +in `vec![elem; len]`"##, + }, Lint { label: "clippy::rc_mutex", description: r##"Checks for `Rc>`."## }, + Lint { + label: "clippy::read_line_without_trim", + description: r##"Looks for calls to [`Stdin::read_line`] to read a line from the standard input +into a string, then later attempting to parse this string into a type without first trimming it, which will +always fail because the string has a trailing newline in it."##, + }, + Lint { + label: "clippy::read_zero_byte_vec", + description: r##"This lint catches reads into a zero-length `Vec`. +Especially in the case of a call to `with_capacity`, this lint warns that read +gets the number of bytes from the `Vec`'s length, not its capacity."##, + }, + Lint { + label: "clippy::readonly_write_lock", + description: r##"Looks for calls to `RwLock::write` where the lock is only used for reading."##, + }, + Lint { + label: "clippy::recursive_format_impl", + description: r##"Checks for format trait implementations (e.g. `Display`) with a recursive call to itself +which uses `self` as a parameter. +This is typically done indirectly with the `write!` macro or with `to_string()`."##, + }, Lint { label: "clippy::redundant_allocation", - description: r##"Checks for use of redundant allocations anywhere in the code."##, + description: r##"Checks for usage of redundant allocations anywhere in the code."##, + }, + Lint { + label: "clippy::redundant_as_str", + description: r##"Checks for usage of `as_str()` on a `String`` chained with a method available on the `String` itself."##, + }, + Lint { + label: "clippy::redundant_async_block", + description: r##"Checks for `async` block that only returns `await` on a future."##, + }, + Lint { + label: "clippy::redundant_at_rest_pattern", + description: r##"Checks for `[all @ ..]` patterns."##, }, Lint { label: "clippy::redundant_clone", @@ -6246,6 +12166,10 @@ are defined."##, description: r##"Checks for closures which only invoke a method on the closure argument and can be replaced by referencing the method directly."##, }, + Lint { + label: "clippy::redundant_comparisons", + description: r##"Checks for ineffective double comparisons against constants."##, + }, Lint { label: "clippy::redundant_else", description: r##"Checks for `else` blocks that can be removed without changing semantics."##, @@ -6259,6 +12183,14 @@ argument and can be replaced by referencing the method directly."##, description: r##"Checks for fields in struct literals where shorthands could be used."##, }, + Lint { + label: "clippy::redundant_guards", + description: r##"Checks for unnecessary guards in match expressions."##, + }, + Lint { + label: "clippy::redundant_locals", + description: r##"Checks for redundant redefinitions of local bindings."##, + }, Lint { label: "clippy::redundant_pattern", description: r##"Checks for patterns in the form `name @ _`."##, @@ -6282,19 +12214,22 @@ do not change the type."##, label: "clippy::redundant_static_lifetimes", description: r##"Checks for constants and statics with an explicit `'static` lifetime."##, }, + Lint { + label: "clippy::redundant_type_annotations", + description: r##"Warns about needless / redundant type annotations."##, + }, Lint { label: "clippy::ref_binding_to_reference", description: r##"Checks for `ref` bindings which create a reference to a reference."##, }, - Lint { - label: "clippy::ref_in_deref", - description: r##"Checks for references in expressions that use -auto dereference."##, - }, Lint { label: "clippy::ref_option_ref", description: r##"Checks for usage of `&Option<&T>`."##, }, + Lint { + label: "clippy::ref_patterns", + description: r##"Checks for usages of the `ref` keyword."##, + }, Lint { label: "clippy::regex_macro", description: r##"Nothing. This lint has been deprecated."##, @@ -6313,10 +12248,19 @@ they are equivalent to `1`. (Related discussion in [rust-clippy#7306](https://gi label: "clippy::replace_consts", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { + label: "clippy::reserve_after_initialization", + description: r##"Informs the user about a more concise way to create a vector with a known capacity."##, + }, Lint { label: "clippy::rest_pat_in_fully_bound_structs", description: r##"Checks for unnecessary '..' pattern binding on struct when all fields are explicitly matched."##, }, + Lint { + label: "clippy::result_large_err", + description: r##"Checks for functions that return `Result` with an unusually large +`Err`-variant."##, + }, Lint { label: "clippy::result_map_or_into_option", description: r##"Checks for usage of `_.map_or(None, Some)`."##, @@ -6339,7 +12283,7 @@ implements `std::error::Error`."##, Lint { label: "clippy::reversed_empty_ranges", description: r##"Checks for range expressions `x..y` where both `x` and `y` -are constant and `x` is greater or equal to `y`."##, +are constant and `x` is greater to `y`. Also triggers if `x` is equal to `y` when they are conditions to a `for` loop."##, }, Lint { label: "clippy::same_functions_in_if_condition", @@ -6359,6 +12303,16 @@ one from a trait, another not from trait."##, label: "clippy::search_is_some", description: r##"Checks for an iterator or string search (such as `find()`, `position()`, or `rposition()`) followed by a call to `is_some()` or `is_none()`."##, + }, + Lint { + label: "clippy::seek_from_current", + description: r##"Checks an argument of `seek` method of `Seek` trait +and if it start seek from `SeekFrom::Current(0)`, suggests `stream_position` instead."##, + }, + Lint { + label: "clippy::seek_to_start_instead_of_rewind", + description: r##"Checks for jumps to the start of a stream that implements `Seek` +and uses the `seek` method providing `Start` as parameter."##, }, Lint { label: "clippy::self_assignment", @@ -6370,13 +12324,22 @@ one from a trait, another not from trait."##, }, Lint { label: "clippy::self_named_module_files", - description: r##"Checks that module layout uses only mod.rs files."##, + description: r##"Checks that module layout uses only `mod.rs` files."##, }, Lint { label: "clippy::semicolon_if_nothing_returned", description: r##"Looks for blocks of expressions and fires if the last expression returns `()` but is not followed by a semicolon."##, }, + Lint { + label: "clippy::semicolon_inside_block", + description: r##"Suggests moving the semicolon after a block to the inside of the block, after its last +expression."##, + }, + Lint { + label: "clippy::semicolon_outside_block", + description: r##"Suggests moving the semicolon from a block's final expression outside of the block."##, + }, Lint { label: "clippy::separated_literal_suffix", description: r##"Warns if literal suffixes are separated by an underscore. @@ -6419,15 +12382,43 @@ statement."##, implementation of a `std` trait (see [llogiq's blog post](http://llogiq.github.io/2015/07/30/traits.html) for further information) instead of an inherent implementation."##, + }, + Lint { + label: "clippy::should_panic_without_expect", + description: r##"Checks for `#[should_panic]` attributes without specifying the expected panic message."##, + }, + Lint { + label: "clippy::significant_drop_in_scrutinee", + description: r##"Checks for temporaries returned from function calls in a match scrutinee that have the +`clippy::has_significant_drop` attribute."##, + }, + Lint { + label: "clippy::significant_drop_tightening", + description: r##"Searches for elements marked with `#[clippy::has_significant_drop]` that could be early +dropped but are in fact dropped at the end of their scopes. In other words, enforces the +tightening of their possible lifetimes."##, }, Lint { label: "clippy::similar_names", - description: r##"Checks for names that are very similar and thus confusing."##, + description: r##"Checks for names that are very similar and thus confusing. + +Note: this lint looks for similar names throughout each +scope. To allow it, you need to allow it on the scope +level, not on the name that is reported."##, + }, + Lint { + label: "clippy::single_call_fn", + description: r##"Checks for functions that are only used once. Does not lint tests."##, }, Lint { label: "clippy::single_char_add_str", description: r##"Warns when using `push_str`/`insert_str` with a single-character string literal where `push`/`insert` with a `char` would work fine."##, + }, + Lint { + label: "clippy::single_char_lifetime_names", + description: r##"Checks for lifetimes with names which are one character +long."##, }, Lint { label: "clippy::single_char_pattern", @@ -6445,18 +12436,32 @@ where `push`/`insert` with a `char` would work fine."##, Lint { label: "clippy::single_match", description: r##"Checks for matches with a single arm where an `if let` -will usually suffice."##, +will usually suffice. + +This intentionally does not lint if there are comments +inside of the other arm, so as to allow the user to document +why having another explicit pattern with an empty body is necessary, +or because the comments need to be preserved for other reasons."##, }, Lint { label: "clippy::single_match_else", description: r##"Checks for matches with two arms where an `if let else` will usually suffice."##, }, + Lint { + label: "clippy::single_range_in_vec_init", + description: r##"Checks for `Vec` or array initializations that contain only one range."##, + }, Lint { label: "clippy::size_of_in_element_count", description: r##"Detects expressions where `size_of::` or `size_of_val::` is used as a count of elements of type `T`"##, + }, + Lint { + label: "clippy::size_of_ref", + description: r##"Checks for calls to `std::mem::size_of_val()` where the argument is +a reference to a reference."##, }, Lint { label: "clippy::skip_while_next", @@ -6469,9 +12474,17 @@ count of elements of type `T`"##, Lint { label: "clippy::stable_sort_primitive", description: r##"When sorting primitive values (integers, bools, chars, as well -as arrays, slices, and tuples of such items), it is better to +as arrays, slices, and tuples of such items), it is typically better to use an unstable sort than a stable sort."##, }, + Lint { + label: "clippy::std_instead_of_alloc", + description: r##"Finds items imported through `std` when available through `alloc`."##, + }, + Lint { + label: "clippy::std_instead_of_core", + description: r##"Finds items imported through `std` when available through `core`."##, + }, Lint { label: "clippy::str_to_string", description: r##"This lint checks for `.to_string()` method calls on values of type `&str`."##, @@ -6501,6 +12514,10 @@ match."##, description: r##"Checks for the `as_bytes` method called on string literals that contain only ASCII characters."##, }, + Lint { + label: "clippy::string_lit_chars_any", + description: r##"Checks for `.chars().any(|i| i == c)`."##, + }, Lint { label: "clippy::string_slice", description: r##"Checks for slice operations on strings"##, @@ -6532,9 +12549,18 @@ subtracting elements in an Add impl."##, }, Lint { label: "clippy::suspicious_assignment_formatting", - description: r##"Checks for use of the nonexistent `=*`, `=!` and `=-` + description: r##"Checks for usage of the non-existent `=*`, `=!` and `=-` operators."##, }, + Lint { + label: "clippy::suspicious_command_arg_space", + description: r##"Checks for `Command::arg()` invocations that look like they +should be multiple arguments instead, such as `arg(-t ext2)`."##, + }, + Lint { + label: "clippy::suspicious_doc_comments", + description: r##"Detects the use of outer doc comments (`///`, `/**`) followed by a bang (`!`): `///!`"##, + }, Lint { label: "clippy::suspicious_else_formatting", description: r##"Checks for formatting of `else`. It lints if the `else` @@ -6561,12 +12587,24 @@ of binary operators nearby."##, (https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and related functions with either zero or one splits."##, }, + Lint { + label: "clippy::suspicious_to_owned", + description: r##"Checks for the usage of `_.to_owned()`, on a `Cow<'_, _>`."##, + }, Lint { label: "clippy::suspicious_unary_op_formatting", description: r##"Checks the formatting of a unary operator on the right hand side of a binary operator. It lints if there is no space between the binary and unary operators, but there is a space between the unary and its operand."##, }, + Lint { + label: "clippy::suspicious_xor_used_as_pow", + description: r##"Warns for a Bitwise XOR (`^`) operator being probably confused as a powering. It will not trigger if any of the numbers are not in decimal."##, + }, + Lint { + label: "clippy::swap_ptr_to_ref", + description: r##"Checks for calls to `core::mem::swap` where either parameter is derived from a pointer"##, + }, Lint { label: "clippy::tabs_in_doc_comments", description: r##"Checks doc comments for usage of tab characters."##, @@ -6577,12 +12615,13 @@ but there is a space between the unary and its operand."##, assign a value in it."##, }, Lint { - label: "clippy::to_digit_is_some", - description: r##"Checks for `.to_digit(..).is_some()` on `char`s."##, + label: "clippy::tests_outside_test_module", + description: r##"Triggers when a testing function (marked with the `#[test]` attribute) isn't inside a testing module +(marked with `#[cfg(test)]`)."##, }, Lint { - label: "clippy::to_string_in_display", - description: r##"Checks for uses of `to_string()` in `Display` traits."##, + label: "clippy::to_digit_is_some", + description: r##"Checks for `.to_digit(..).is_some()` on `char`s."##, }, Lint { label: "clippy::to_string_in_format_args", @@ -6610,7 +12649,7 @@ in a macro that does formatting."##, }, Lint { label: "clippy::trait_duplication_in_bounds", - description: r##"Checks for cases where generics are being used and multiple + description: r##"Checks for cases where generics or trait objects are being used and multiple syntax specifications for trait bounds are used simultaneously."##, }, Lint { @@ -6633,6 +12672,15 @@ syntax specifications for trait bounds are used simultaneously."##, label: "clippy::transmute_int_to_float", description: r##"Checks for transmutes from an integer to a float."##, }, + Lint { + label: "clippy::transmute_int_to_non_zero", + description: r##"Checks for transmutes from integers to `NonZero*` types, and suggests their `new_unchecked` +method instead."##, + }, + Lint { + label: "clippy::transmute_null_to_fn", + description: r##"Checks for null function pointer creation through transmute."##, + }, Lint { label: "clippy::transmute_num_to_bytes", description: r##"Checks for transmutes from a number to an array of `u8`"##, @@ -6646,6 +12694,11 @@ from a reference to a reference."##, label: "clippy::transmute_ptr_to_ref", description: r##"Checks for transmutes from a pointer to a reference."##, }, + Lint { + label: "clippy::transmute_undefined_repr", + description: r##"Checks for transmutes between types which do not have a representation defined relative to +each other."##, + }, Lint { label: "clippy::transmutes_expressible_as_ptr_casts", description: r##"Checks for transmutes that could be a pointer cast."##, @@ -6654,6 +12707,10 @@ from a reference to a reference."##, label: "clippy::transmuting_null", description: r##"Checks for transmute calls which would receive a null pointer."##, }, + Lint { + label: "clippy::trim_split_whitespace", + description: r##"Warns about calling `str::trim` (or variants) before `str::split_whitespace`."##, + }, Lint { label: "clippy::trivial_regex", description: r##"Checks for trivial [regex](https://crates.io/crates/regex) @@ -6665,25 +12722,51 @@ creation (with `Regex::new`, `RegexBuilder::new`, or `RegexSet::new`)."##, the argument type is `Copy` and small enough to be more efficient to always pass by value."##, }, - Lint { label: "clippy::try_err", description: r##"Checks for usages of `Err(x)?`."## }, + Lint { label: "clippy::try_err", description: r##"Checks for usage of `Err(x)?`."## }, + Lint { + label: "clippy::tuple_array_conversions", + description: r##"Checks for tuple<=>array conversions that are not done with `.into()`."##, + }, Lint { label: "clippy::type_complexity", description: r##"Checks for types used in structs, parameters and `let` declarations above a certain complexity threshold."##, }, + Lint { + label: "clippy::type_id_on_box", + description: r##"Looks for calls to ` as Any>::type_id`."##, + }, Lint { label: "clippy::type_repetition_in_bounds", description: r##"This lint warns about unnecessary type repetitions in trait bounds"##, }, Lint { - label: "clippy::undocumented_unsafe_blocks", - description: r##"Checks for `unsafe` blocks without a `// Safety: ` comment -explaining why the unsafe operations performed inside -the block are safe."##, + label: "clippy::unchecked_duration_subtraction", + description: r##"Lints subtraction between an [`Instant`] and a [`Duration`]."##, }, Lint { - label: "clippy::undropped_manually_drops", - description: r##"Prevents the safe `std::mem::drop` function from being called on `std::mem::ManuallyDrop`."##, + label: "clippy::undocumented_unsafe_blocks", + description: r##"Checks for `unsafe` blocks and impls without a `// SAFETY: ` comment +explaining why the unsafe operations performed inside +the block are safe. + +Note the comment must appear on the line(s) preceding the unsafe block +with nothing appearing in between. The following is ok: +```rust +foo( + // SAFETY: + // This is a valid safety comment + unsafe { *x } +) +``` +But neither of these are: +```rust +// SAFETY: +// This is not a valid safety comment +foo( + /* SAFETY: Neither is this */ unsafe { *x }, +); +```"##, }, Lint { label: "clippy::unicode_not_nfc", @@ -6704,6 +12787,11 @@ that is not equal to its description: r##"Checks for `set_len()` call that creates `Vec` with uninitialized elements. This is commonly caused by calling `set_len()` right after allocating or reserving a buffer with `new()`, `default()`, `with_capacity()`, or `reserve()`."##, + }, + Lint { + label: "clippy::uninlined_format_args", + description: r##"Detect when a variable is not inlined in a format string, +and suggests to inline it."##, }, Lint { label: "clippy::unit_arg", @@ -6721,24 +12809,41 @@ comparisons (like `==` and `<`) and asserts."##, description: r##"Checks for functions that expect closures of type Fn(...) -> Ord where the implemented closure returns the unit type. The lint also suggests to remove the semi-colon at the end of the statement if present."##, + }, + Lint { + label: "clippy::unnecessary_box_returns", + description: r##"Checks for a return type containing a `Box` where `T` implements `Sized` + +The lint ignores `Box` where `T` is larger than `unnecessary_box_size`, +as returning a large `T` directly may be detrimental to performance."##, }, Lint { label: "clippy::unnecessary_cast", - description: r##"Checks for casts to the same type, casts of int literals to integer types -and casts of float literals to float types."##, + description: r##"Checks for casts to the same type, casts of int literals to integer types, casts of float +literals to float types and casts between raw pointers without changing type or constness."##, }, Lint { label: "clippy::unnecessary_filter_map", - description: r##"Checks for `filter_map` calls which could be replaced by `filter` or `map`. + description: r##"Checks for `filter_map` calls that could be replaced by `filter` or `map`. More specifically it checks if the closure provided is only performing one of the filter or map operations and suggests the appropriate option."##, + }, + Lint { + label: "clippy::unnecessary_find_map", + description: r##"Checks for `find_map` calls that could be replaced by `find` or `map`. More +specifically it checks if the closure provided is only performing one of the +find or map operations and suggests the appropriate option."##, }, Lint { label: "clippy::unnecessary_fold", - description: r##"Checks for using `fold` when a more succinct alternative exists. + description: r##"Checks for usage of `fold` when a more succinct alternative exists. Specifically, this checks for `fold`s which could be replaced by `any`, `all`, `sum` or `product`."##, }, + Lint { + label: "clippy::unnecessary_join", + description: r##"Checks for usage of `.collect::>().join()` on iterators."##, + }, Lint { label: "clippy::unnecessary_lazy_evaluations", description: r##"As the counterpart to `or_fun_call`, this lint looks for unnecessary @@ -6750,7 +12855,16 @@ simpler code: - `and_then` to `and` - `or_else` to `or` - `get_or_insert_with` to `get_or_insert` - - `ok_or_else` to `ok_or`"##, + - `ok_or_else` to `ok_or` + - `then` to `then_some` (for msrv >= 1.62.0)"##, + }, + Lint { + label: "clippy::unnecessary_literal_unwrap", + description: r##"Checks for `.unwrap()` related calls on `Result`s and `Option`s that are constructed."##, + }, + Lint { + label: "clippy::unnecessary_map_on_constructor", + description: r##"Suggest removing the use of a may (or map_err) method when an Option or Result is being construted."##, }, Lint { label: "clippy::unnecessary_mut_passed", @@ -6761,6 +12875,19 @@ requires an immutable reference."##, label: "clippy::unnecessary_operation", description: r##"Checks for expression statements that can be reduced to a sub-expression."##, + }, + Lint { + label: "clippy::unnecessary_owned_empty_strings", + description: r##"Detects cases of owned empty strings being passed as an argument to a function expecting `&str`"##, + }, + Lint { + label: "clippy::unnecessary_safety_comment", + description: r##"Checks for `// SAFETY: ` comments on safe code."##, + }, + Lint { + label: "clippy::unnecessary_safety_doc", + description: r##"Checks for the doc comments of publicly visible +safe functions and traits and warns if there is a `# Safety` section."##, }, Lint { label: "clippy::unnecessary_self_imports", @@ -6768,8 +12895,13 @@ sub-expression."##, }, Lint { label: "clippy::unnecessary_sort_by", - description: r##"Detects uses of `Vec::sort_by` passing in a closure + description: r##"Checks for usage of `Vec::sort_by` passing in a closure which compares the two arguments, either directly or indirectly."##, + }, + Lint { + label: "clippy::unnecessary_struct_initialization", + description: r##"Checks for initialization of a `struct` by copying a base without setting +any field."##, }, Lint { label: "clippy::unnecessary_to_owned", @@ -6854,10 +12986,24 @@ types have different ABI, size or alignment."##, label: "clippy::unused_collect", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { + label: "clippy::unused_format_specs", + description: r##"Detects [formatting parameters] that have no effect on the output of +`format!()`, `println!()` or similar macros."##, + }, Lint { label: "clippy::unused_io_amount", description: r##"Checks for unused written/read amount."##, }, + Lint { + label: "clippy::unused_peekable", + description: r##"Checks for the creation of a `peekable` iterator that is never `.peek()`ed"##, + }, + Lint { + label: "clippy::unused_rounding", + description: r##"Detects cases where a whole-number literal float is being rounded, using +the `floor`, `ceil`, or `round` methods."##, + }, Lint { label: "clippy::unused_self", description: r##"Checks methods that contain a `self` argument but don't use it"##, @@ -6876,13 +13022,17 @@ by nibble or byte."##, description: r##"Checks for functions of type `Result` that contain `expect()` or `unwrap()`"##, }, Lint { - label: "clippy::unwrap_or_else_default", - description: r##"Checks for usages of `_.unwrap_or_else(Default::default)` on `Option` and -`Result` values."##, + label: "clippy::unwrap_or_default", + description: r##"Checks for usages of the following functions with an argument that constructs a default value +(e.g., `Default::default` or `String::new`): +- `unwrap_or` +- `unwrap_or_else` +- `or_insert` +- `or_insert_with`"##, }, Lint { label: "clippy::unwrap_used", - description: r##"Checks for `.unwrap()` calls on `Option`s and on `Result`s."##, + description: r##"Checks for `.unwrap()` or `.unwrap_err()` calls on `Result`s and `.unwrap()` call on `Option`s."##, }, Lint { label: "clippy::upper_case_acronyms", @@ -6890,7 +13040,7 @@ by nibble or byte."##, }, Lint { label: "clippy::use_debug", - description: r##"Checks for use of `Debug` formatting. The purpose of this + description: r##"Checks for usage of `Debug` formatting. The purpose of this lint is to catch debugging remnants."##, }, Lint { @@ -6913,10 +13063,17 @@ types before and after the call are the same."##, description: r##"Checks for `extern crate` and `use` items annotated with lint attributes. -This lint permits `#[allow(unused_imports)]`, `#[allow(deprecated)]`, -`#[allow(unreachable_pub)]`, `#[allow(clippy::wildcard_imports)]` and -`#[allow(clippy::enum_glob_use)]` on `use` items and `#[allow(unused_imports)]` on -`extern crate` items with a `#[macro_use]` attribute."##, +This lint permits lint attributes for lints emitted on the items themself. +For `use` items these lints are: +* deprecated +* unreachable_pub +* unused_imports +* clippy::enum_glob_use +* clippy::macro_use_imports +* clippy::wildcard_imports + +For `extern crate` items these lints are: +* `unused_imports` on items with `#[macro_use]`"##, }, Lint { label: "clippy::useless_conversion", @@ -6940,17 +13097,24 @@ and transmutes that could be a cast."##, }, Lint { label: "clippy::useless_vec", - description: r##"Checks for usage of `&vec![..]` when using `&[..]` would + description: r##"Checks for usage of `vec![..]` when using `[..]` would be possible."##, }, Lint { label: "clippy::vec_box", - description: r##"Checks for use of `Vec>` where T: Sized anywhere in the code. + description: r##"Checks for usage of `Vec>` where T: Sized anywhere in the code. Check the [Box documentation](https://doc.rust-lang.org/std/boxed/index.html) for more information."##, }, Lint { label: "clippy::vec_init_then_push", - description: r##"Checks for calls to `push` immediately after creating a new `Vec`."##, + description: r##"Checks for calls to `push` immediately after creating a new `Vec`. + +If the `Vec` is created using `with_capacity` this will only lint if the capacity is a +constant and the number of pushes is greater than or equal to the initial capacity. + +If the `Vec` is extended after the initial sequence of pushes and it was default initialized +then this will only lint after there were at least four pushes. This number may change in +the future."##, }, Lint { label: "clippy::vec_resize_to_zero", @@ -6963,7 +13127,7 @@ to `trailing_zeros`"##, }, Lint { label: "clippy::verbose_file_reads", - description: r##"Checks for use of File::read_to_end and File::read_to_string."##, + description: r##"Checks for usage of File::read_to_end and File::read_to_string."##, }, Lint { label: "clippy::vtable_address_comparisons", @@ -7020,18 +13184,19 @@ print a newline."##, }, Lint { label: "clippy::wrong_self_convention", - description: r##"Checks for methods with certain name prefixes and which -doesn't match how self is taken. The actual rules are: + 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 |`&self` or none | any | -|`to_` | `_mut` |`&mut self` | any | -|`to_` | not `_mut` |`self` | `Copy` | -|`to_` | not `_mut` |`&self` | not `Copy` | +|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 e475c5cd66b6..da5a951f0b7b 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 = 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::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, 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 { - 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 9be1d3663493..a0cfd3836ddf 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs @@ -9,7 +9,7 @@ use syntax::{ algo, ast::{ self, edit_in_place::Removable, make, AstNode, HasAttrs, HasModuleItem, HasVisibility, - PathSegmentKind, + PathSegmentKind, UseTree, }, ted, Direction, NodeOrToken, SyntaxKind, SyntaxNode, }; @@ -157,6 +157,29 @@ impl ImportScope { /// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur. pub fn insert_use(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) { + insert_use_with_alias_option(scope, path, cfg, None); +} + +pub fn insert_use_as_alias(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) { + let text: &str = "use foo as _"; + let parse = syntax::SourceFile::parse(text); + let node = parse + .tree() + .syntax() + .descendants() + .find_map(UseTree::cast) + .expect("Failed to make ast node `Rename`"); + let alias = node.rename(); + + insert_use_with_alias_option(scope, path, cfg, alias); +} + +fn insert_use_with_alias_option( + scope: &ImportScope, + path: ast::Path, + cfg: &InsertUseConfig, + alias: Option, +) { let _p = profile::span("insert_use"); let mut mb = match cfg.granularity { ImportGranularity::Crate => Some(MergeBehavior::Crate), @@ -176,7 +199,8 @@ pub fn insert_use(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) { } let use_item = - make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update(); + make::use_(None, make::use_tree(path.clone(), None, alias, false)).clone_for_update(); + // merge into existing imports if possible if let Some(mb) = mb { let filter = |it: &_| !(cfg.skip_glob_imports && ast::Use::is_simple_glob(it)); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs index b92e367f7e12..01d2f1970c38 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 27b6321f3a7a..ff84e9ffaeec 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 3f7a3ec2d0fd..67ed44f08b7f 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 f699f999baf7..3e89159c2c6e 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 c7d5f3613d4b..c8cf87d3c205 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/tests/sourcegen_lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/tests/sourcegen_lints.rs @@ -1,4 +1,5 @@ -//! Generates descriptors structure for unstable feature from Unstable Book +//! Generates descriptor structures for unstable features from the unstable book +//! and lints from rustc, rustdoc, and clippy. use std::{borrow::Cow, fs, path::Path}; use itertools::Itertools; @@ -6,6 +7,8 @@ use stdx::format_to; use test_utils::project_root; use xshell::{cmd, Shell}; +const DESTINATION: &str = "crates/ide-db/src/generated/lints.rs"; + /// This clones rustc repo, and so is not worth to keep up-to-date. We update /// manually by un-ignoring the test from time to time. #[test] @@ -14,11 +17,21 @@ fn sourcegen_lint_completions() { let sh = &Shell::new().unwrap(); let rust_repo = project_root().join("./target/rust"); - if !rust_repo.exists() { + if rust_repo.exists() { + cmd!(sh, "git -C {rust_repo} pull --rebase").run().unwrap(); + } else { cmd!(sh, "git clone --depth=1 https://github.com/rust-lang/rust {rust_repo}") .run() .unwrap(); } + // need submodules for Cargo to parse the workspace correctly + cmd!( + sh, + "git -C {rust_repo} submodule update --init --recursive --depth=1 -- + compiler library src/tools" + ) + .run() + .unwrap(); let mut contents = String::from( r" @@ -27,17 +40,28 @@ pub struct Lint { pub label: &'static str, pub description: &'static str, } + pub struct LintGroup { pub lint: Lint, pub children: &'static [&'static str], } + ", ); generate_lint_descriptor(sh, &mut contents); contents.push('\n'); - generate_feature_descriptor(&mut contents, &rust_repo.join("src/doc/unstable-book/src")); + let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); + let unstable_book = project_root().join("./target/unstable-book-gen"); + cmd!( + sh, + "{cargo} run --manifest-path {rust_repo}/src/tools/unstable-book-gen/Cargo.toml -- + {rust_repo}/library {rust_repo}/compiler {rust_repo}/src {unstable_book}" + ) + .run() + .unwrap(); + generate_feature_descriptor(&mut contents, &unstable_book.join("src")); contents.push('\n'); let lints_json = project_root().join("./target/clippy_lints.json"); @@ -51,41 +75,60 @@ pub struct LintGroup { let contents = sourcegen::add_preamble("sourcegen_lints", sourcegen::reformat(contents)); - let destination = project_root().join("crates/ide_db/src/generated/lints.rs"); + let destination = project_root().join(DESTINATION); sourcegen::ensure_file_contents(destination.as_path(), &contents); } +/// Parses the output of `rustdoc -Whelp` and prints `Lint` and `LintGroup` constants into `buf`. +/// +/// As of writing, the output of `rustc -Whelp` (not rustdoc) has the following format: +/// +/// ```text +/// Lint checks provided by rustc: +/// +/// name default meaning +/// ---- ------- ------- +/// +/// ... +/// +/// Lint groups provided by rustc: +/// +/// name sub-lints +/// ---- --------- +/// +/// ... +/// ``` +/// +/// `rustdoc -Whelp` (and any other custom `rustc` driver) adds another two +/// tables after the `rustc` ones, with a different title but the same format. fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { - // FIXME: rustdoc currently requires an input file for -Whelp cc https://github.com/rust-lang/rust/pull/88831 - let file = project_root().join(file!()); - let stdout = cmd!(sh, "rustdoc -W help {file}").read().unwrap(); - let start_lints = stdout.find("---- ------- -------").unwrap(); - let start_lint_groups = stdout.find("---- ---------").unwrap(); - let start_lints_rustdoc = - stdout.find("Lint checks provided by plugins loaded by this crate:").unwrap(); - let start_lint_groups_rustdoc = - stdout.find("Lint groups provided by plugins loaded by this crate:").unwrap(); + let stdout = cmd!(sh, "rustdoc -Whelp").read().unwrap(); + let lints_pat = "---- ------- -------\n"; + let lint_groups_pat = "---- ---------\n"; + let lints = find_and_slice(&stdout, lints_pat); + let lint_groups = find_and_slice(lints, lint_groups_pat); + let lints_rustdoc = find_and_slice(lint_groups, lints_pat); + let lint_groups_rustdoc = find_and_slice(lints_rustdoc, lint_groups_pat); buf.push_str(r#"pub const DEFAULT_LINTS: &[Lint] = &["#); buf.push('\n'); - let lints = stdout[start_lints..].lines().skip(1).take_while(|l| !l.is_empty()).map(|line| { + let lints = lints.lines().take_while(|l| !l.is_empty()).map(|line| { let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap(); let (_default_level, description) = rest.trim().split_once(char::is_whitespace).unwrap(); (name.trim(), Cow::Borrowed(description.trim()), vec![]) }); - let lint_groups = - stdout[start_lint_groups..].lines().skip(1).take_while(|l| !l.is_empty()).map(|line| { - let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); - ( - name.trim(), - format!("lint group for: {}", lints.trim()).into(), - lints - .split_ascii_whitespace() - .map(|s| s.trim().trim_matches(',').replace('-', "_")) - .collect(), - ) - }); + let lint_groups = lint_groups.lines().take_while(|l| !l.is_empty()).map(|line| { + let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); + ( + name.trim(), + format!("lint group for: {}", lints.trim()).into(), + lints + .split_ascii_whitespace() + .map(|s| s.trim().trim_matches(',').replace('-', "_")) + .collect(), + ) + }); let lints = lints .chain(lint_groups) @@ -94,7 +137,8 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { for (name, description, ..) in &lints { push_lint_completion(buf, &name.replace('-', "_"), description); } - buf.push_str("];\n"); + buf.push_str("];\n\n"); + buf.push_str(r#"pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &["#); for (name, description, children) in &lints { if !children.is_empty() { @@ -115,27 +159,23 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { buf.push_str(r#"pub const RUSTDOC_LINTS: &[Lint] = &["#); buf.push('\n'); - let lints_rustdoc = - stdout[start_lints_rustdoc..].lines().skip(2).take_while(|l| !l.is_empty()).map(|line| { - let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap(); - let (_default_level, description) = - rest.trim().split_once(char::is_whitespace).unwrap(); - (name.trim(), Cow::Borrowed(description.trim()), vec![]) - }); + let lints_rustdoc = lints_rustdoc.lines().take_while(|l| !l.is_empty()).map(|line| { + let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap(); + let (_default_level, description) = rest.trim().split_once(char::is_whitespace).unwrap(); + (name.trim(), Cow::Borrowed(description.trim()), vec![]) + }); let lint_groups_rustdoc = - stdout[start_lint_groups_rustdoc..].lines().skip(2).take_while(|l| !l.is_empty()).map( - |line| { - let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); - ( - name.trim(), - format!("lint group for: {}", lints.trim()).into(), - lints - .split_ascii_whitespace() - .map(|s| s.trim().trim_matches(',').replace('-', "_")) - .collect(), - ) - }, - ); + lint_groups_rustdoc.lines().take_while(|l| !l.is_empty()).map(|line| { + let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap(); + ( + name.trim(), + format!("lint group for: {}", lints.trim()).into(), + lints + .split_ascii_whitespace() + .map(|s| s.trim().trim_matches(',').replace('-', "_")) + .collect(), + ) + }); let lints_rustdoc = lints_rustdoc .chain(lint_groups_rustdoc) @@ -145,7 +185,7 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { for (name, description, ..) in &lints_rustdoc { push_lint_completion(buf, &name.replace('-', "_"), description) } - buf.push_str("];\n"); + buf.push_str("];\n\n"); buf.push_str(r#"pub const RUSTDOC_LINT_GROUPS: &[LintGroup] = &["#); for (name, description, children) in &lints_rustdoc { @@ -157,14 +197,24 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) { buf.push_str("];\n"); } +#[track_caller] +fn find_and_slice<'a>(i: &'a str, p: &str) -> &'a str { + let idx = i.find(p).unwrap(); + &i[idx + p.len()..] +} + +/// Parses the unstable book `src_dir` and prints a constant with the list of +/// unstable features into `buf`. +/// +/// It does this by looking for all `.md` files in the `language-features` and +/// `library-features` directories, and using the file name as the feature +/// name, and the file contents as the feature description. fn generate_feature_descriptor(buf: &mut String, src_dir: &Path) { let mut features = ["language-features", "library-features"] .into_iter() .flat_map(|it| sourcegen::list_files(&src_dir.join(it))) - .filter(|path| { - // Get all `.md ` files - path.extension().unwrap_or_default().to_str().unwrap_or_default() == "md" - }) + // Get all `.md` files + .filter(|path| path.extension() == Some("md".as_ref())) .map(|path| { let feature_ident = path.file_stem().unwrap().to_str().unwrap().replace('-', "_"); let doc = fs::read_to_string(path).unwrap(); @@ -196,7 +246,7 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) { let mut clippy_lints: Vec = Vec::new(); let mut clippy_groups: std::collections::BTreeMap> = Default::default(); - for line in file_content.lines().map(|line| line.trim()) { + for line in file_content.lines().map(str::trim) { if let Some(line) = line.strip_prefix(r#""id": ""#) { let clippy_lint = ClippyLint { id: line.strip_suffix(r#"","#).expect("should be suffixed by comma").into(), @@ -211,12 +261,19 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) { .push(clippy_lints.last().unwrap().id.clone()); } } else if let Some(line) = line.strip_prefix(r#""docs": ""#) { - let prefix_to_strip = r#" ### What it does"#; - let line = match line.strip_prefix(prefix_to_strip) { - Some(line) => line, + let header = "### What it does"; + let line = match line.find(header) { + Some(idx) => &line[idx + header.len()..], None => { - eprintln!("unexpected clippy prefix for {}", clippy_lints.last().unwrap().id); - continue; + let id = &clippy_lints.last().unwrap().id; + // these just don't have the common header + let allowed = ["allow_attributes", "read_line_without_trim"]; + if allowed.contains(&id.as_str()) { + line + } else { + eprintln!("\nunexpected clippy prefix for {id}, line={line:?}\n",); + continue; + } } }; // Only take the description, any more than this is a lot of additional data we would embed into the exe diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/field_shorthand.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/field_shorthand.rs index 3b69640af9b8..9ed8199ae4d0 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 235062bf531f..85dbb7e6f263 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -111,6 +111,31 @@ fn some_fn() { let what_aweird_formatting = 10; another_func(what_aweird_formatting); } +"#, + ); + + check_fix( + r#" +static S: i32 = M::A; + +mod $0M { + pub const A: i32 = 10; +} + +mod other { + use crate::M::A; +} +"#, + r#" +static S: i32 = m::A; + +mod m { + pub const A: i32 = 10; +} + +mod other { + use crate::m::A; +} "#, ); } @@ -175,10 +200,10 @@ fn NonSnakeCaseName() {} fn incorrect_function_params() { check_diagnostics( r#" -fn foo(SomeParam: u8) {} +fn foo(SomeParam: u8) { _ = SomeParam; } // ^^^^^^^^^ 💡 warn: Parameter `SomeParam` should have snake_case name, e.g. `some_param` -fn foo2(ok_param: &str, CAPS_PARAM: u8) {} +fn foo2(ok_param: &str, CAPS_PARAM: u8) { _ = (ok_param, CAPS_PARAM); } // ^^^^^^^^^^ 💡 warn: Parameter `CAPS_PARAM` should have snake_case name, e.g. `caps_param` "#, ); @@ -188,6 +213,7 @@ fn foo2(ok_param: &str, CAPS_PARAM: u8) {} fn incorrect_variable_names() { check_diagnostics( r#" +#[allow(unused)] fn foo() { let SOME_VALUE = 10; // ^^^^^^^^^^ 💡 warn: Variable `SOME_VALUE` should have snake_case name, e.g. `some_value` @@ -294,6 +320,7 @@ impl someStruct { // ^^^^^^^^ 💡 warn: Function `SomeFunc` should have snake_case name, e.g. `some_func` let WHY_VAR_IS_CAPS = 10; // ^^^^^^^^^^^^^^^ 💡 warn: Variable `WHY_VAR_IS_CAPS` should have snake_case name, e.g. `why_var_is_caps` + _ = WHY_VAR_IS_CAPS; } } "#, @@ -306,6 +333,7 @@ impl someStruct { r#" enum Option { Some, None } +#[allow(unused)] fn main() { match Option::None { None => (), @@ -322,6 +350,7 @@ fn main() { r#" enum Option { Some, None } +#[allow(unused)] fn main() { match Option::None { SOME_VAR @ None => (), @@ -349,7 +378,9 @@ enum E { } mod F { - fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) {} + fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) { + _ = BAD_NAME_HI; + } } "#, ); @@ -395,7 +426,7 @@ fn qualify() { #[test] // Issue #8809. fn parenthesized_parameter() { - check_diagnostics(r#"fn f((O): _) {}"#) + check_diagnostics(r#"fn f((O): _) { _ = O; }"#) } #[test] @@ -472,7 +503,9 @@ mod CheckBadStyle { mod F { #![allow(non_snake_case)] - fn CheckItWorksWithModAttr(BAD_NAME_HI: u8) {} + fn CheckItWorksWithModAttr(BAD_NAME_HI: u8) { + _ = BAD_NAME_HI; + } } #[allow(non_snake_case, non_camel_case_types)] @@ -510,17 +543,20 @@ fn NonSnakeCaseName(some_var: u8) -> u8 { #[deny(nonstandard_style)] mod CheckNonstandardStyle { + //^^^^^^^^^^^^^^^^^^^^^ 💡 error: Module `CheckNonstandardStyle` should have snake_case name, e.g. `check_nonstandard_style` fn HiImABadFnName() {} //^^^^^^^^^^^^^^ 💡 error: Function `HiImABadFnName` should have snake_case name, e.g. `hi_im_abad_fn_name` } #[deny(warnings)] mod CheckBadStyle { + //^^^^^^^^^^^^^ 💡 error: Module `CheckBadStyle` should have snake_case name, e.g. `check_bad_style` struct fooo; //^^^^ 💡 error: Structure `fooo` should have CamelCase name, e.g. `Fooo` } mod F { + //^ 💡 warn: Module `F` should have snake_case name, e.g. `f` #![deny(non_snake_case)] fn CheckItWorksWithModAttr() {} //^^^^^^^^^^^^^^^^^^^^^^^ 💡 error: Function `CheckItWorksWithModAttr` should have snake_case name, e.g. `check_it_works_with_mod_attr` @@ -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 8265e0b1c117..06ba13bcc55c 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -23,12 +23,7 @@ pub(crate) fn mismatched_tuple_struct_pat_arg_count( Diagnostic::new( DiagnosticCode::RustcHardError("E0023"), message, - invalid_args_range( - ctx, - d.expr_or_pat.clone().map(|it| it.either(Into::into, Into::into)), - d.expected, - d.found, - ), + invalid_args_range(ctx, d.expr_or_pat.clone().map(Into::into), d.expected, d.found), ) } @@ -131,7 +126,7 @@ fn f() { zero(); } fn simple_free_fn_one() { check_diagnostics( r#" -fn one(arg: u8) {} +fn one(_arg: u8) {} fn f() { one(); } //^^ error: expected 1 argument, found 0 "#, @@ -139,7 +134,7 @@ fn f() { one(); } check_diagnostics( r#" -fn one(arg: u8) {} +fn one(_arg: u8) {} fn f() { one(1); } "#, ); @@ -176,7 +171,7 @@ fn f() { check_diagnostics( r#" struct S; -impl S { fn method(&self, arg: u8) {} } +impl S { fn method(&self, _arg: u8) {} } fn f() { S.method(); @@ -187,7 +182,7 @@ impl S { fn method(&self, arg: u8) {} } check_diagnostics( r#" struct S; -impl S { fn method(&self, arg: u8) {} } +impl S { fn method(&self, _arg: u8) {} } fn f() { S::method(&S, 0); @@ -335,8 +330,8 @@ struct S; impl S { fn method(#[cfg(NEVER)] self) {} - fn method2(#[cfg(NEVER)] self, arg: u8) {} - fn method3(self, #[cfg(NEVER)] arg: u8) {} + fn method2(#[cfg(NEVER)] self, _arg: u8) {} + fn method3(self, #[cfg(NEVER)] _arg: u8) {} } extern "C" { @@ -365,8 +360,8 @@ fn main() { r#" #[rustc_legacy_const_generics(1, 3)] fn mixed( - a: u8, - b: i8, + _a: u8, + _b: i8, ) {} fn f() { @@ -376,8 +371,8 @@ fn f() { #[rustc_legacy_const_generics(1, 3)] fn b( - a: u8, - b: u8, + _a: u8, + _b: u8, ) {} fn g() { @@ -403,7 +398,7 @@ fn f( // ^^ error: this pattern has 0 fields, but the corresponding tuple struct has 2 fields S(e, f, .., g, d): S // ^^^^^^^^^ error: this pattern has 4 fields, but the corresponding tuple struct has 2 fields -) {} +) { _ = (a, b, c, d, e, f, g); } "#, ) } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs index acc31cd117ad..c09be3fee7e1 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -39,7 +39,7 @@ pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingField d.field_list_parent_path .clone() .map(SyntaxNodePtr::from) - .unwrap_or_else(|| d.field_list_parent.clone().either(|it| it.into(), |it| it.into())), + .unwrap_or_else(|| d.field_list_parent.clone().into()), ); Diagnostic::new_with_syntax_node_ptr(ctx, DiagnosticCode::RustcHardError("E0063"), message, ptr) @@ -58,10 +58,8 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option ctx.sema.scope(ptr.to_node(&root).syntax()).map(|it| it.module()), - Either::Right(ptr) => ctx.sema.scope(ptr.to_node(&root).syntax()).map(|it| it.module()), - }; + let current_module = + ctx.sema.scope(d.field_list_parent.to_node(&root).syntax()).map(|it| it.module()); let build_text_edit = |parent_syntax, new_syntax: &SyntaxNode, old_syntax| { let edit = { @@ -87,9 +85,8 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option { - let field_list_parent = record_expr.to_node(&root); + match &d.field_list_parent.to_node(&root) { + Either::Left(field_list_parent) => { let missing_fields = ctx.sema.record_literal_missing_fields(&field_list_parent); let mut locals = FxHashMap::default(); @@ -152,8 +149,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option { - let field_list_parent = record_pat.to_node(&root); + Either::Right(field_list_parent) => { let missing_fields = ctx.sema.record_pattern_missing_fields(&field_list_parent); let old_field_list = field_list_parent.record_pat_field_list()?; @@ -290,6 +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 06b03d3d1989..84267d3d9069 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 { Some(T), None } +#[allow(unused)] fn main() { // `Never` is deliberately not defined so that it's an uninferred type. match Option::::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 70b26009bae0..0f695b2745a8 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 3aa4aa97026a..886aefeb575f 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 d056e5c85cc0..ee096a100aaa 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs @@ -324,6 +324,7 @@ fn main() { let x_own = 2; let ref mut x_ref = x_own; //^^^^^^^^^^^^^ 💡 error: cannot mutate immutable variable `x_own` + _ = x_ref; } "#, ); @@ -331,7 +332,7 @@ fn main() { r#" struct Foo; impl Foo { - fn method(&mut self, x: i32) {} + fn method(&mut self, _x: i32) {} } fn main() { let x = Foo; @@ -391,6 +392,7 @@ fn main() { //^^^^^ 💡 warn: variable does not need to be mutable x = 7; //^^^^^ 💡 error: cannot mutate immutable variable `x` + _ = y; } } } @@ -404,12 +406,14 @@ fn main() { // there would be no mutability error for locals in dead code. Rustc tries to // not emit `unused_mut` in this case, but since it works without `mut`, and // special casing it is not trivial, we emit it. + + // Update: now MIR based `unused-variable` is taking over `unused-mut` for the same reason. check_diagnostics( r#" fn main() { return; let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -419,7 +423,7 @@ fn main() { fn main() { loop {} let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -440,7 +444,7 @@ fn main(b: bool) { g(); } let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -454,7 +458,7 @@ fn main(b: bool) { return; } let mut x = 2; - //^^^^^ 💡 warn: variable does not need to be mutable + //^^^^^ warn: unused variable &mut x; } "#, @@ -536,6 +540,7 @@ fn main() { (k @ 5, ref mut t) if { continue; } => { //^^^^^^^^^ 💡 error: cannot mutate immutable variable `z` *t = 5; + _ = k; } _ => { let y = (1, 2); @@ -588,6 +593,7 @@ fn main() { b = 1; c = (2, 3); d = 3; + _ = (c, b, d); } } "#, @@ -600,6 +606,7 @@ fn main() { r#" fn f(mut x: i32) { //^^^^^ 💡 warn: variable does not need to be mutable + f(x + 2); } "#, ); @@ -615,8 +622,11 @@ fn f(x: i32) { r#" fn f((x, y): (i32, i32)) { let t = [0; 2]; - x = 5; - //^^^^^ 💡 error: cannot mutate immutable variable `x` + x = 5; + //^^^^^ 💡 error: cannot mutate immutable variable `x` + _ = x; + _ = y; + _ = t; } "#, ); @@ -645,6 +655,7 @@ fn f(x: [(i32, u8); 10]) { //^^^^^ 💡 warn: variable does not need to be mutable a = 2; //^^^^^ 💡 error: cannot mutate immutable variable `a` + _ = b; } } "#, @@ -666,6 +677,7 @@ fn f(x: [(i32, u8); 10]) { //^^^^^ 💡 error: cannot mutate immutable variable `a` c = 2; //^^^^^ 💡 error: cannot mutate immutable variable `c` + _ = (b, d); } } } @@ -696,18 +708,18 @@ fn f() { fn overloaded_index() { check_diagnostics( r#" -//- minicore: index +//- minicore: index, copy use core::ops::{Index, IndexMut}; struct Foo; impl Index for Foo { type Output = (i32, u8); - fn index(&self, index: usize) -> &(i32, u8) { + fn index(&self, _index: usize) -> &(i32, u8) { &(5, 2) } } impl IndexMut for Foo { - fn index_mut(&mut self, index: usize) -> &mut (i32, u8) { + fn index_mut(&mut self, _index: usize) -> &mut (i32, u8) { &mut (5, 2) } } @@ -715,26 +727,32 @@ fn f() { let mut x = Foo; //^^^^^ 💡 warn: variable does not need to be mutable let y = &x[2]; + _ = (x, y); let x = Foo; let y = &mut x[2]; //^💡 error: cannot mutate immutable variable `x` + _ = (x, y); let mut x = &mut Foo; //^^^^^ 💡 warn: variable does not need to be mutable let y: &mut (i32, u8) = &mut x[2]; + _ = (x, y); let x = Foo; let ref mut y = x[7]; //^ 💡 error: cannot mutate immutable variable `x` + _ = (x, y); let (ref mut y, _) = x[3]; //^ 💡 error: cannot mutate immutable variable `x` + _ = y; match x[10] { //^ 💡 error: cannot mutate immutable variable `x` - (ref y, _) => (), - (_, ref mut y) => (), + (ref y, 5) => _ = y, + (_, ref mut y) => _ = y, } let mut x = Foo; let mut i = 5; //^^^^^ 💡 warn: variable does not need to be mutable let y = &mut x[i]; + _ = y; } "#, ); @@ -744,7 +762,7 @@ fn f() { fn overloaded_deref() { check_diagnostics( r#" -//- minicore: deref_mut +//- minicore: deref_mut, copy use core::ops::{Deref, DerefMut}; struct Foo; @@ -763,21 +781,27 @@ fn f() { let mut x = Foo; //^^^^^ 💡 warn: variable does not need to be mutable let y = &*x; + _ = (x, y); let x = Foo; let y = &mut *x; //^^ 💡 error: cannot mutate immutable variable `x` + _ = (x, y); let x = Foo; + //^ warn: unused variable let x = Foo; let y: &mut (i32, u8) = &mut x; //^^^^^^ 💡 error: cannot mutate immutable variable `x` + _ = (x, y); let ref mut y = *x; //^^ 💡 error: cannot mutate immutable variable `x` + _ = y; let (ref mut y, _) = *x; //^^ 💡 error: cannot mutate immutable variable `x` + _ = y; match *x { //^^ 💡 error: cannot mutate immutable variable `x` - (ref y, _) => (), - (_, ref mut y) => (), + (ref y, 5) => _ = y, + (_, ref mut y) => _ = y, } } "#, @@ -866,6 +890,7 @@ pub fn test() { data: 0 } ); + _ = tree; } "#, ); @@ -925,6 +950,7 @@ fn fn_once(mut x: impl FnOnce(u8) -> u8) -> u8 { let x = X; let closure4 = || { x.mutate(); }; //^ 💡 error: cannot mutate immutable variable `x` + _ = (closure2, closure3, closure4); } "#, ); @@ -941,7 +967,9 @@ fn fn_once(mut x: impl FnOnce(u8) -> u8) -> u8 { z = 3; let mut k = z; //^^^^^ 💡 warn: variable does not need to be mutable + _ = k; }; + _ = (x, closure); } "#, ); @@ -958,6 +986,7 @@ fn f() { } } }; + _ = closure; } "#, ); @@ -972,7 +1001,8 @@ fn f() { let mut x = X; let c2 = || { x = X; x }; let mut x = X; - let c2 = move || { x = X; }; + let c3 = move || { x = X; }; + _ = (c1, c2, c3); } "#, ); @@ -1023,7 +1053,7 @@ fn x(t: &[u8]) { a = 2; //^^^^^ 💡 error: cannot mutate immutable variable `a` - + _ = b; } _ => {} } @@ -1079,6 +1109,7 @@ fn f() { let x = Box::new(5); let closure = || *x = 2; //^ 💡 error: cannot mutate immutable variable `x` + _ = closure; } "#, ); @@ -1156,6 +1187,7 @@ macro_rules! mac { fn main2() { let mut x = mac![]; //^^^^^ 💡 warn: variable does not need to be mutable + _ = x; } "#, ); 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 290c16c9d247..ee8a9c95793c 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs @@ -13,7 +13,7 @@ use crate::{fix, Assist, Diagnostic, DiagnosticCode, DiagnosticsContext}; // // This diagnostic is triggered if created structure does not have field provided in record. pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) -> Diagnostic { - let node = d.field.clone().map(|it| it.either(Into::into, Into::into)); + let node = d.field.clone().map(Into::into); if d.private { // FIXME: quickfix to add required visibility Diagnostic::new_with_syntax_node_ptr( @@ -35,15 +35,13 @@ pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) -> Option> { // FIXME: quickfix for pattern - match &d.field.value { - Either::Left(ptr) => { - let root = ctx.sema.db.parse_or_expand(d.field.file_id); - missing_record_expr_field_fixes( - &ctx.sema, - d.field.file_id.original_file(ctx.sema.db), - &ptr.to_node(&root), - ) - } + let root = ctx.sema.db.parse_or_expand(d.field.file_id); + match &d.field.value.to_node(&root) { + Either::Left(node) => missing_record_expr_field_fixes( + &ctx.sema, + d.field.file_id.original_file(ctx.sema.db), + node, + ), _ => None, } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs index c44d28e77f6d..a828b8b4fd29 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 083ef3e8dc16..d15233d15c2c 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 15bd28c00dfd..14454fe8dc40 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -1,4 +1,3 @@ -use either::Either; use hir::{db::ExpandDatabase, ClosureStyle, HirDisplay, InFile, Type}; use ide_db::{famous_defs::FamousDefs, source_change::SourceChange}; use syntax::{ @@ -14,9 +13,11 @@ use crate::{adjusted_display_range, fix, Assist, Diagnostic, DiagnosticCode, Dia // This diagnostic is triggered when the type of an expression or pattern does not match // the expected type. pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Diagnostic { - let display_range = match &d.expr_or_pat { - Either::Left(expr) => { - adjusted_display_range::(ctx, expr.clone().map(|it| it.into()), &|expr| { + let display_range = match &d.expr_or_pat.value { + expr if ast::Expr::can_cast(expr.kind()) => adjusted_display_range::( + ctx, + InFile { file_id: d.expr_or_pat.file_id, value: expr.syntax_node_ptr() }, + &|expr| { let salient_token_range = match expr { ast::Expr::IfExpr(it) => it.if_token()?.text_range(), ast::Expr::LoopExpr(it) => it.loop_token()?.text_range(), @@ -32,10 +33,15 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) cov_mark::hit!(type_mismatch_range_adjustment); Some(salient_token_range) - }) - } - Either::Right(pat) => { - ctx.sema.diagnostics_display_range(pat.clone().map(|it| it.into())).range + }, + ), + pat => { + ctx.sema + .diagnostics_display_range(InFile { + file_id: d.expr_or_pat.file_id, + value: pat.syntax_node_ptr(), + }) + .range } }; let mut diag = Diagnostic::new( @@ -57,14 +63,12 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Option> { let mut fixes = Vec::new(); - match &d.expr_or_pat { - Either::Left(expr_ptr) => { - add_reference(ctx, d, expr_ptr, &mut fixes); - add_missing_ok_or_some(ctx, d, expr_ptr, &mut fixes); - remove_semicolon(ctx, d, expr_ptr, &mut fixes); - str_ref_to_owned(ctx, d, expr_ptr, &mut fixes); - } - Either::Right(_pat_ptr) => {} + if let Some(expr_ptr) = d.expr_or_pat.value.clone().cast::() { + let expr_ptr = &InFile { file_id: d.expr_or_pat.file_id, value: expr_ptr.clone() }; + add_reference(ctx, d, expr_ptr, &mut fixes); + add_missing_ok_or_some(ctx, d, expr_ptr, &mut fixes); + remove_semicolon(ctx, d, expr_ptr, &mut fixes); + str_ref_to_owned(ctx, d, expr_ptr, &mut fixes); } if fixes.is_empty() { @@ -205,7 +209,7 @@ fn main() { test(123); //^^^ 💡 error: expected &i32, found i32 } -fn test(arg: &i32) {} +fn test(_arg: &i32) {} "#, ); } @@ -217,13 +221,13 @@ fn test(arg: &i32) {} fn main() { test(123$0); } -fn test(arg: &i32) {} +fn test(_arg: &i32) {} "#, r#" fn main() { test(&123); } -fn test(arg: &i32) {} +fn test(_arg: &i32) {} "#, ); } @@ -235,13 +239,13 @@ fn test(arg: &i32) {} fn main() { test($0123); } -fn test(arg: &mut i32) {} +fn test(_arg: &mut i32) {} "#, r#" fn main() { test(&mut 123); } -fn test(arg: &mut i32) {} +fn test(_arg: &mut i32) {} "#, ); } @@ -254,13 +258,13 @@ fn test(arg: &mut i32) {} fn main() { test($0[1, 2, 3]); } -fn test(arg: &[i32]) {} +fn test(_arg: &[i32]) {} "#, r#" fn main() { test(&[1, 2, 3]); } -fn test(arg: &[i32]) {} +fn test(_arg: &[i32]) {} "#, ); } @@ -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 { fn f() -> Rate { // FIXME: add some error loop {} } - fn run(t: Rate<5>) { + fn run(_t: Rate<5>) { } fn main() { run(f()) // FIXME: remove this error @@ -426,7 +430,7 @@ fn div(x: i32, y: i32) -> Option { check_diagnostics( r#" pub struct Rate(T); - fn run(t: Rate) { + fn run(_t: Rate) { } fn main() { run(Rate::<_, _, _>(5)); @@ -650,7 +654,7 @@ fn h() { r#" struct X(T); -fn foo(x: X) {} +fn foo(_x: X) {} fn test1() { // Unknown might be `i32`, so we should not emit type mismatch here. foo(X(42)); 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 4af67227115d..4e215a89d793 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs @@ -142,8 +142,8 @@ fn t() -> T { loop {} } check_diagnostics( r#" fn main() { - let x = [(); _]; - let y: [(); 10] = [(); _]; + let _x = [(); _]; + let _y: [(); 10] = [(); _]; _ = 0; (_,) = (1,); } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs new file mode 100644 index 000000000000..28ccf474b40b --- /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 ebe197a6790e..fe5567544e83 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 37a177622162..ac15b6aba618 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 21934b9480ef..e0b64fe7988e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -180,26 +180,24 @@ fn hover_simple( descended() .filter_map(|token| { let node = token.parent()?; - let class = IdentClass::classify_token(sema, token)?; - if let IdentClass::Operator(OperatorClass::Await(_)) = class { + match IdentClass::classify_node(sema, &node)? { // It's better for us to fall back to the keyword hover here, // rendering poll is very confusing - return None; + IdentClass::Operator(OperatorClass::Await(_)) => None, + + IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { + decl, + .. + }) => Some(vec![(Definition::ExternCrateDecl(decl), node)]), + + class => Some( + class + .definitions() + .into_iter() + .zip(iter::repeat(node)) + .collect::>(), + ), } - if let IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { - decl, - .. - }) = class - { - return Some(vec![(Definition::ExternCrateDecl(decl), node)]); - } - Some( - class - .definitions() - .into_iter() - .zip(iter::once(node).cycle()) - .collect::>(), - ) }) .flatten() .unique_by(|&(def, _)| def) diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index f72ce37d1d94..d0a02fd0dba2 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 81d6db564ff5..e54bc48d555b 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(x: T) -> U; - "##]], + fn arith_offset(dst: *const T, offset: isize) -> *const T; + } + ``` + + As with any other FFI functions, these are always `unsafe` to call. + + "#]], ) } 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 12e46c0f8837..4152e6067551 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 aee03d218adf..2320c95b4a1a 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 2d528c642558..07cdddd15f82 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -308,11 +308,7 @@ pub(crate) fn runnable_fn( sema: &Semantics<'_, RootDatabase>, def: hir::Function, ) -> Option { - let name = def.name(sema.db).to_smol_str(); - - let root = def.module(sema.db).krate().root_module(); - - let kind = if name == "main" && def.module(sema.db) == root { + let kind = if def.is_main(sema.db) { RunnableKind::Bin } else { let test_id = || { @@ -320,7 +316,9 @@ pub(crate) fn runnable_fn( let def: hir::ModuleDef = def.into(); def.canonical_path(sema.db) }; - canonical_path.map(TestId::Path).unwrap_or(TestId::Name(name)) + canonical_path + .map(TestId::Path) + .unwrap_or(TestId::Name(def.name(sema.db).to_smol_str())) }; if def.is_test(sema.db) { @@ -587,6 +585,9 @@ mod tests { $0 fn main() {} +#[export_name = "main"] +fn __cortex_m_rt_main_trampoline() {} + #[test] fn test_foo() {} @@ -604,7 +605,7 @@ mod not_a_root { fn main() {} } "#, - &[TestMod, Bin, Test, Test, Test, Bench], + &[TestMod, Bin, Bin, Test, Test, Test, Bench], expect![[r#" [ Runnable { @@ -613,7 +614,7 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 0..190, + full_range: 0..253, name: "", kind: Module, }, @@ -642,8 +643,22 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 15..39, - focus_range: 26..34, + full_range: 15..76, + focus_range: 42..71, + name: "__cortex_m_rt_main_trampoline", + kind: Function, + }, + kind: Bin, + cfg: None, + }, + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 78..102, + focus_range: 89..97, name: "test_foo", kind: Function, }, @@ -663,8 +678,8 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 41..92, - focus_range: 73..87, + full_range: 104..155, + focus_range: 136..150, name: "test_full_path", kind: Function, }, @@ -684,8 +699,8 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 94..128, - focus_range: 115..123, + full_range: 157..191, + focus_range: 178..186, name: "test_foo", kind: Function, }, @@ -705,8 +720,8 @@ mod not_a_root { file_id: FileId( 0, ), - full_range: 130..152, - focus_range: 142..147, + full_range: 193..215, + focus_range: 205..210, name: "bench", kind: Function, }, @@ -1655,12 +1670,18 @@ macro_rules! gen2 { } } } +macro_rules! gen_main { + () => { + fn main() {} + } +} mod tests { gen!(); } gen2!(); +gen_main!(); "#, - &[TestMod, TestMod, Test, Test, TestMod], + &[TestMod, TestMod, Test, Test, TestMod, Bin], expect![[r#" [ Runnable { @@ -1669,7 +1690,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 0..237, + full_range: 0..315, name: "", kind: Module, }, @@ -1684,8 +1705,8 @@ gen2!(); file_id: FileId( 0, ), - full_range: 202..227, - focus_range: 206..211, + full_range: 267..292, + focus_range: 271..276, name: "tests", kind: Module, description: "mod tests", @@ -1701,7 +1722,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 218..225, + full_range: 283..290, name: "foo_test", kind: Function, }, @@ -1721,7 +1742,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 228..236, + full_range: 293..301, name: "foo_test2", kind: Function, }, @@ -1741,7 +1762,7 @@ gen2!(); file_id: FileId( 0, ), - full_range: 228..236, + full_range: 293..301, name: "tests2", kind: Module, description: "mod tests2", @@ -1751,6 +1772,19 @@ gen2!(); }, cfg: None, }, + Runnable { + use_name_in_title: false, + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 302..314, + name: "main", + kind: Function, + }, + kind: Bin, + cfg: None, + }, ] "#]], ); diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs index bb01c81d66fb..dd72484b3807 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 b40509715baf..d21850bcff3e 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 2f6332abd259..3802978f4941 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 2934d26674d7..d784321c7c7a 100644 --- a/src/tools/rust-analyzer/crates/intern/src/lib.rs +++ b/src/tools/rust-analyzer/crates/intern/src/lib.rs @@ -33,13 +33,10 @@ impl Interned { // - if not, box it up, insert it, and return a clone // This needs to be atomic (locking the shard) to avoid races with other thread, which could // insert the same object between us looking it up and inserting it. - match shard.raw_entry_mut().from_key_hashed_nocheck(hash as u64, &obj) { + match shard.raw_entry_mut().from_key_hashed_nocheck(hash, &obj) { RawEntryMut::Occupied(occ) => Self { arc: occ.key().clone() }, RawEntryMut::Vacant(vac) => Self { - arc: vac - .insert_hashed_nocheck(hash as u64, Arc::new(obj), SharedValue::new(())) - .0 - .clone(), + arc: vac.insert_hashed_nocheck(hash, Arc::new(obj), SharedValue::new(())).0.clone(), }, } } @@ -54,13 +51,10 @@ impl Interned { // - if not, box it up, insert it, and return a clone // This needs to be atomic (locking the shard) to avoid races with other thread, which could // insert the same object between us looking it up and inserting it. - match shard.raw_entry_mut().from_key_hashed_nocheck(hash as u64, s) { + match shard.raw_entry_mut().from_key_hashed_nocheck(hash, s) { RawEntryMut::Occupied(occ) => Self { arc: occ.key().clone() }, RawEntryMut::Vacant(vac) => Self { - arc: vac - .insert_hashed_nocheck(hash as u64, Arc::from(s), SharedValue::new(())) - .0 - .clone(), + arc: vac.insert_hashed_nocheck(hash, Arc::from(s), SharedValue::new(())).0.clone(), }, } } diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander.rs b/src/tools/rust-analyzer/crates/mbe/src/expander.rs index f2d89d3efe5a..908048c99042 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 9d886a1c979a..a439c9c50d6c 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 09e62c35278e..efb326323f91 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 74eae9151a26..846da28cb016 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 36c52953a024..b9e7566fdf9b 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 c155e8aaf67b..fcfd1a50719b 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 2c47e3d086d6..57005a6834c9 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 000000000000..7603c9099daa --- /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 000000000000..b2d06e490bd6 --- /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 000000000000..e8d8ff8cefb4 --- /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 000000000000..e74847137b1e --- /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 000000000000..1b4424ba5c78 --- /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 000000000000..1b78ffc28a00 --- /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 000000000000..b1e1364d4c2c --- /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 000000000000..291f99d8020c --- /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 000000000000..0cd1747208e4 --- /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 000000000000..2499516d3fa9 --- /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 c848ac368e4f..fd20ca57ac6c 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 b54930f5e699..65460d02cb27 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 66e58cc298f4..07172a4ecc0a 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 454ee0a5f617..15f52c113c11 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 000000000000..39e35a81ee27 --- /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 000000000000..0adf7b8d2f02 --- /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 fb0f3ab7d174..68cd40c040b3 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 e47808a2cc9f..ca3d6e0596ca 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -96,6 +96,8 @@ pub struct CargoConfig { pub extra_env: FxHashMap, pub invocation_strategy: InvocationStrategy, pub invocation_location: InvocationLocation, + /// Optional path to use instead of `target` when building + pub target_dir: Option, } pub type Package = Idx; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index 7410f0a3a668..c85b3e53cda2 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 2fa14fc7e283..a7d0a0b0dfc4 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 dcb3ca6581cb..230ff5f9b86a 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 419440b6df7b..fe5022f8606d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs @@ -131,6 +131,9 @@ xflags::xflags! { /// The output path where the SCIP file will be written to. Defaults to `index.scip`. optional --output path: PathBuf + + /// A path to an json configuration file that can be used to customize cargo behavior. + optional --config-path config_path: PathBuf } } } @@ -239,6 +242,7 @@ pub struct Scip { pub path: PathBuf, pub output: Option, + pub config_path: Option, } impl RustAnalyzer { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs index 8c056fff000e..30e11402cd8d 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 ea3a21241cb6..c8df4255d96b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -91,6 +91,12 @@ config_data! { /// and should therefore include `--message-format=json` or a similar /// option. /// + /// If there are multiple linked projects/workspaces, this command is invoked for + /// each of them, with the working directory being the workspace root + /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten + /// by changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#` and + /// `#rust-analyzer.cargo.buildScripts.invocationLocation#`. + /// /// By default, a cargo invocation will be constructed for the configured /// targets and features, with the following base command line: /// @@ -182,9 +188,11 @@ config_data! { /// Cargo, you might also want to change /// `#rust-analyzer.cargo.buildScripts.overrideCommand#`. /// - /// If there are multiple linked projects, this command is invoked for - /// each of them, with the working directory being the project root - /// (i.e., the folder containing the `Cargo.toml`). + /// If there are multiple linked projects/workspaces, this command is invoked for + /// each of them, with the working directory being the workspace root + /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten + /// by changing `#rust-analyzer.cargo.check.invocationStrategy#` and + /// `#rust-analyzer.cargo.check.invocationLocation#`. /// /// An example command would be: /// @@ -209,6 +217,8 @@ config_data! { completion_autoself_enable: bool = "true", /// Whether to add parenthesis and argument snippets when completing function. completion_callable_snippets: CallableCompletionDef = "\"fill_arguments\"", + /// Whether to show full function/method signatures in completion docs. + completion_fullFunctionSignatures_enable: bool = "false", /// Maximum number of completions to return. If `None`, the limit is infinite. completion_limit: Option = "null", /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. @@ -470,6 +480,14 @@ config_data! { /// tests or binaries. For example, it may be `--release`. runnables_extraArgs: Vec = "[]", + /// Optional path to a rust-analyzer specific target directory. + /// This prevents rust-analyzer's `cargo check` from locking the `Cargo.lock` + /// at the expense of duplicating build artifacts. + /// + /// Set to `true` to use a subdirectory of the existing target directory or + /// set to a path relative to the workspace to use that path. + rust_analyzerTargetDir: Option = "null", + /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private /// projects, or "discover" to try to automatically find it if the `rustc-dev` component /// is installed. @@ -565,6 +583,7 @@ pub struct Config { data: ConfigData, detached_files: Vec, snippets: Vec, + 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, + 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 { + 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" => 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 731580557c29..f8bc66ff8e74 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 b8a1a39be193..06c27332d440 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 5a11012b93cf..2c402552919f 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 23074493aeee..aca91570f7c2 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 { + 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 e49b5768fa46..106b99cb9352 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 8b5c92c66023..56b5fcef3c2f 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 000000000000..a313507bff31 --- /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 000000000000..13fcbc491937 --- /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 000000000000..fd44e6c6d0f4 --- /dev/null +++ b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs @@ -0,0 +1,379 @@ +//! This file is a port of only the necessary features from https://github.com/chris-morgan/anymap version 1.0.0-beta.2 for use within rust-analyzer. +//! Copyright © 2014–2022 Chris Morgan. COPYING: https://github.com/chris-morgan/anymap/blob/master/COPYING" +//! Note that the license is changed from Blue Oak Model 1.0.0 or MIT or Apache-2.0 to MIT OR Apache-2.0 +//! +//! This implementation provides a safe and convenient store for one value of each type. +//! +//! Your starting point is [`Map`]. It has an example. +//! +//! # Cargo features +//! +//! This implementation has two independent features, each of which provides an implementation providing +//! types `Map`, `AnyMap`, `OccupiedEntry`, `VacantEntry`, `Entry` and `RawMap`: +//! +//! - **std** (default, *enabled* in this build): +//! an implementation using `std::collections::hash_map`, placed in the crate root +//! (e.g. `anymap::AnyMap`). + +#![warn(missing_docs, unused_results)] + +use core::convert::TryInto; +use core::hash::Hasher; + +/// A hasher designed to eke a little more speed out, given `TypeId`’s known characteristics. +/// +/// Specifically, this is a no-op hasher that expects to be fed a u64’s worth of +/// randomly-distributed bits. It works well for `TypeId` (eliminating start-up time, so that my +/// get_missing benchmark is ~30ns rather than ~900ns, and being a good deal faster after that, so +/// that my insert_and_get_on_260_types benchmark is ~12μs instead of ~21.5μs), but will +/// panic in debug mode and always emit zeros in release mode for any other sorts of inputs, so +/// yeah, don’t use it! 😀 +#[derive(Default)] +pub struct TypeIdHasher { + value: u64, +} + +impl Hasher for TypeIdHasher { + #[inline] + fn write(&mut self, bytes: &[u8]) { + // This expects to receive exactly one 64-bit value, and there’s no realistic chance of + // that changing, but I don’t want to depend on something that isn’t expressly part of the + // contract for safety. But I’m OK with release builds putting everything in one bucket + // if it *did* change (and debug builds panicking). + debug_assert_eq!(bytes.len(), 8); + let _ = bytes.try_into().map(|array| self.value = u64::from_ne_bytes(array)); + } + + #[inline] + fn finish(&self) -> u64 { + self.value + } +} + +use core::any::{Any, TypeId}; +use core::hash::BuildHasherDefault; +use core::marker::PhantomData; + +use ::std::collections::hash_map::{self, HashMap}; + +/// Raw access to the underlying `HashMap`. +/// +/// This alias is provided for convenience because of the ugly third generic parameter. +pub type RawMap = HashMap, BuildHasherDefault>; + +/// A collection containing zero or one values for any given type and allowing convenient, +/// type-safe access to those values. +/// +/// The type parameter `A` allows you to use a different value type; normally you will want +/// it to be `core::any::Any` (also known as `std::any::Any`), but there are other choices: +/// +/// - If you want the entire map to be cloneable, use `CloneAny` instead of `Any`; with +/// that, you can only add types that implement `Clone` to the map. +/// - You can add on `+ Send` or `+ Send + Sync` (e.g. `Map`) to add those +/// auto traits. +/// +/// Cumulatively, there are thus six forms of map: +/// +/// - [Map]<dyn [core::any::Any]>, +/// also spelled [`AnyMap`] for convenience. +/// - [Map]<dyn [core::any::Any] + Send> +/// - [Map]<dyn [core::any::Any] + Send + Sync> +/// - [Map]<dyn [CloneAny]> +/// - [Map]<dyn [CloneAny] + Send> +/// - [Map]<dyn [CloneAny] + Send + Sync> +/// +/// ## Example +/// +/// (Here using the [`AnyMap`] convenience alias; the first line could use +/// [anymap::Map][Map]::<[core::any::Any]>::new() instead if desired.) +/// +/// ```rust +#[doc = "let mut data = anymap::AnyMap::new();"] +/// assert_eq!(data.get(), None::<&i32>); +/// ``` +/// +/// Values containing non-static references are not permitted. +#[derive(Debug)] +pub struct Map { + raw: RawMap, +} + +/// The most common type of `Map`: just using `Any`; [Map]<dyn [Any]>. +/// +/// Why is this a separate type alias rather than a default value for `Map`? +/// `Map::new()` doesn’t seem to be happy to infer that it should go with the default +/// value. It’s a bit sad, really. Ah well, I guess this approach will do. +pub type AnyMap = Map; +impl Default for Map { + #[inline] + fn default() -> Map { + Map::new() + } +} + +impl Map { + /// Create an empty collection. + #[inline] + pub fn new() -> Map { + Map { raw: RawMap::with_hasher(Default::default()) } + } + + /// Returns a reference to the value stored in the collection for the type `T`, + /// if it exists. + #[inline] + pub fn get>(&self) -> Option<&T> { + self.raw.get(&TypeId::of::()).map(|any| unsafe { any.downcast_ref_unchecked::() }) + } + + /// Gets the entry for the given type in the collection for in-place manipulation + #[inline] + pub fn entry>(&mut self) -> Entry<'_, A, T> { + match self.raw.entry(TypeId::of::()) { + hash_map::Entry::Occupied(e) => { + Entry::Occupied(OccupiedEntry { inner: e, type_: PhantomData }) + } + hash_map::Entry::Vacant(e) => { + Entry::Vacant(VacantEntry { inner: e, type_: PhantomData }) + } + } + } +} + +/// A view into a single occupied location in an `Map`. +pub struct OccupiedEntry<'a, A: ?Sized + Downcast, V: 'a> { + inner: hash_map::OccupiedEntry<'a, TypeId, Box>, + type_: PhantomData, +} + +/// A view into a single empty location in an `Map`. +pub struct VacantEntry<'a, A: ?Sized + Downcast, V: 'a> { + inner: hash_map::VacantEntry<'a, TypeId, Box>, + type_: PhantomData, +} + +/// A view into a single location in an `Map`, which may be vacant or occupied. +pub enum Entry<'a, A: ?Sized + Downcast, V> { + /// An occupied Entry + Occupied(OccupiedEntry<'a, A, V>), + /// A vacant Entry + Vacant(VacantEntry<'a, A, V>), +} + +impl<'a, A: ?Sized + Downcast, V: IntoBox> Entry<'a, A, V> { + /// Ensures a value is in the entry by inserting the result of the default function if + /// empty, and returns a mutable reference to the value in the entry. + #[inline] + pub fn or_insert_with V>(self, default: F) -> &'a mut V { + match self { + Entry::Occupied(inner) => inner.into_mut(), + Entry::Vacant(inner) => inner.insert(default()), + } + } +} + +impl<'a, A: ?Sized + Downcast, V: IntoBox> OccupiedEntry<'a, A, V> { + /// Converts the OccupiedEntry into a mutable reference to the value in the entry + /// with a lifetime bound to the collection itself + #[inline] + pub fn into_mut(self) -> &'a mut V { + unsafe { self.inner.into_mut().downcast_mut_unchecked() } + } +} + +impl<'a, A: ?Sized + Downcast, V: IntoBox> VacantEntry<'a, A, V> { + /// Sets the value of the entry with the VacantEntry's key, + /// and returns a mutable reference to it + #[inline] + pub fn insert(self, value: V) -> &'a mut V { + unsafe { self.inner.insert(value.into_box()).downcast_mut_unchecked() } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Clone, Debug, PartialEq)] + struct A(i32); + #[derive(Clone, Debug, PartialEq)] + struct B(i32); + #[derive(Clone, Debug, PartialEq)] + struct C(i32); + #[derive(Clone, Debug, PartialEq)] + struct D(i32); + #[derive(Clone, Debug, PartialEq)] + struct E(i32); + #[derive(Clone, Debug, PartialEq)] + struct F(i32); + #[derive(Clone, Debug, PartialEq)] + struct J(i32); + + #[test] + fn test_varieties() { + fn assert_send() {} + fn assert_sync() {} + fn assert_debug() {} + assert_send::>(); + assert_send::>(); + assert_sync::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); + assert_send::>(); + assert_send::>(); + assert_sync::>(); + assert_debug::>(); + assert_debug::>(); + assert_debug::>(); + } + + #[test] + fn type_id_hasher() { + use core::any::TypeId; + use core::hash::Hash; + fn verify_hashing_with(type_id: TypeId) { + let mut hasher = TypeIdHasher::default(); + type_id.hash(&mut hasher); + // SAFETY: u64 is valid for all bit patterns. + let _ = hasher.finish(); + } + // Pick a variety of types, just to demonstrate it’s all sane. Normal, zero-sized, unsized, &c. + verify_hashing_with(TypeId::of::()); + verify_hashing_with(TypeId::of::<()>()); + verify_hashing_with(TypeId::of::()); + verify_hashing_with(TypeId::of::<&str>()); + verify_hashing_with(TypeId::of::>()); + } +} + +// impl some traits for dyn Any +use core::fmt; + +#[doc(hidden)] +pub trait CloneToAny { + /// Clone `self` into a new `Box` object. + fn clone_to_any(&self) -> Box; +} + +impl CloneToAny for T { + #[inline] + fn clone_to_any(&self) -> Box { + Box::new(self.clone()) + } +} + +macro_rules! impl_clone { + ($t:ty) => { + impl Clone for Box<$t> { + #[inline] + fn clone(&self) -> Box<$t> { + // SAFETY: this dance is to reapply any Send/Sync marker. I’m not happy about this + // approach, given that I used to do it in safe code, but then came a dodgy + // future-compatibility warning where_clauses_object_safety, which is spurious for + // auto traits but still super annoying (future-compatibility lints seem to mean + // your bin crate needs a corresponding allow!). Although I explained my plight¹ + // and it was all explained and agreed upon, no action has been taken. So I finally + // caved and worked around it by doing it this way, which matches what’s done for + // core::any², so it’s probably not *too* bad. + // + // ¹ https://github.com/rust-lang/rust/issues/51443#issuecomment-421988013 + // ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616 + let clone: Box = (**self).clone_to_any(); + let raw: *mut dyn CloneAny = Box::into_raw(clone); + unsafe { Box::from_raw(raw as *mut $t) } + } + } + + impl fmt::Debug for $t { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad(stringify!($t)) + } + } + }; +} + +/// Methods for downcasting from an `Any`-like trait object. +/// +/// This should only be implemented on trait objects for subtraits of `Any`, though you can +/// implement it for other types and it’ll work fine, so long as your implementation is correct. +pub trait Downcast { + /// Gets the `TypeId` of `self`. + fn type_id(&self) -> TypeId; + + // Note the bound through these downcast methods is 'static, rather than the inexpressible + // concept of Self-but-as-a-trait (where Self is `dyn Trait`). This is sufficient, exceeding + // TypeId’s requirements. Sure, you *can* do CloneAny.downcast_unchecked::() and the + // type system won’t protect you, but that doesn’t introduce any unsafety: the method is + // already unsafe because you can specify the wrong type, and if this were exposing safe + // downcasting, CloneAny.downcast::() would just return an error, which is just as + // correct. + // + // Now in theory we could also add T: ?Sized, but that doesn’t play nicely with the common + // implementation, so I’m doing without it. + + /// Downcast from `&Any` to `&T`, without checking the type matches. + /// + /// # Safety + /// + /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. + unsafe fn downcast_ref_unchecked(&self) -> &T; + + /// Downcast from `&mut Any` to `&mut T`, without checking the type matches. + /// + /// # Safety + /// + /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*. + unsafe fn downcast_mut_unchecked(&mut self) -> &mut T; +} + +/// A trait for the conversion of an object into a boxed trait object. +pub trait IntoBox: Any { + /// Convert self into the appropriate boxed form. + fn into_box(self) -> Box; +} + +macro_rules! implement { + ($any_trait:ident $(+ $auto_traits:ident)*) => { + impl Downcast for dyn $any_trait $(+ $auto_traits)* { + #[inline] + fn type_id(&self) -> TypeId { + self.type_id() + } + + #[inline] + unsafe fn downcast_ref_unchecked(&self) -> &T { + &*(self as *const Self as *const T) + } + + #[inline] + unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { + &mut *(self as *mut Self as *mut T) + } + } + + impl IntoBox for T { + #[inline] + fn into_box(self) -> Box { + Box::new(self) + } + } + } +} + +implement!(Any); +implement!(Any + Send); +implement!(Any + Send + Sync); + +/// [`Any`], but with cloning. +/// +/// Every type with no non-`'static` references that implements `Clone` implements `CloneAny`. +/// See [`core::any`] for more details on `Any` in general. +pub trait CloneAny: Any + CloneToAny {} +impl CloneAny for T {} +implement!(CloneAny); +implement!(CloneAny + Send); +implement!(CloneAny + Send + Sync); +impl_clone!(dyn CloneAny); +impl_clone!(dyn CloneAny + Send); +impl_clone!(dyn CloneAny + Send + Sync); diff --git a/src/tools/rust-analyzer/crates/stdx/src/lib.rs b/src/tools/rust-analyzer/crates/stdx/src/lib.rs index 24990d6a0e71..f26c7f6dfc2d 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/lib.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/lib.rs @@ -12,6 +12,7 @@ pub mod panic_context; pub mod non_empty_vec; pub mod rand; pub mod thread; +pub mod anymap; pub use always_assert::{always, never}; @@ -89,6 +90,57 @@ where words.join("_") } +// Taken from rustc. +pub fn to_camel_case(ident: &str) -> String { + ident + .trim_matches('_') + .split('_') + .filter(|component| !component.is_empty()) + .map(|component| { + let mut camel_cased_component = String::with_capacity(component.len()); + + let mut new_word = true; + let mut prev_is_lower_case = true; + + for c in component.chars() { + // Preserve the case if an uppercase letter follows a lowercase letter, so that + // `camelCase` is converted to `CamelCase`. + if prev_is_lower_case && c.is_uppercase() { + new_word = true; + } + + if new_word { + camel_cased_component.extend(c.to_uppercase()); + } else { + camel_cased_component.extend(c.to_lowercase()); + } + + prev_is_lower_case = c.is_lowercase(); + new_word = false; + } + + camel_cased_component + }) + .fold((String::new(), None), |(acc, prev): (_, Option), next| { + // separate two components with an underscore if their boundary cannot + // be distinguished using an uppercase/lowercase case distinction + let join = prev + .and_then(|prev| { + let f = next.chars().next()?; + let l = prev.chars().last()?; + Some(!char_has_case(l) && !char_has_case(f)) + }) + .unwrap_or(false); + (acc + if join { "_" } else { "" } + &next, Some(next)) + }) + .0 +} + +// Taken from rustc. +pub fn char_has_case(c: char) -> bool { + c.is_lowercase() || c.is_uppercase() +} + pub fn replace(buf: &mut String, from: char, to: &str) { if !buf.contains(from) { return; diff --git a/src/tools/rust-analyzer/crates/stdx/src/macros.rs b/src/tools/rust-analyzer/crates/stdx/src/macros.rs index 1a9982fa8b2a..d71e418c89bc 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 e5aa34365187..bca0cbc36d1a 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 5ee0c4792846..dc92366d1c7a 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 a150d9e6c07d..a85e1d1d9d0e 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::(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 17e311c0c502..31a858b91a7d 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -433,7 +433,6 @@ pub fn record_field( ast_from_text(&format!("struct S {{ {visibility}{name}: {ty}, }}")) } -// TODO pub fn block_expr( stmts: impl IntoIterator, tail_expr: Option, @@ -853,6 +852,10 @@ pub fn self_param() -> ast::SelfParam { ast_from_text("fn f(&self) { }") } +pub fn mut_self_param() -> ast::SelfParam { + ast_from_text("fn f(&mut self) { }") +} + pub fn ret_type(ty: ast::Type) -> ast::RetType { ast_from_text(&format!("fn f() -> {ty} {{ }}")) } @@ -973,6 +976,11 @@ pub fn tuple_field(visibility: Option, ty: ast::Type) -> ast::T ast_from_text(&format!("struct f({visibility}{ty});")) } +pub fn variant_list(variants: impl IntoIterator) -> ast::VariantList { + let variants = variants.into_iter().join(", "); + ast_from_text(&format!("enum f {{ {variants} }}")) +} + pub fn variant(name: ast::Name, field_list: Option) -> ast::Variant { let field_list = match field_list { None => String::new(), @@ -1037,6 +1045,19 @@ pub fn struct_( ast_from_text(&format!("{visibility}struct {strukt_name}{type_params}{field_list}{semicolon}",)) } +pub fn enum_( + visibility: Option, + enum_name: ast::Name, + variant_list: ast::VariantList, +) -> ast::Enum { + let visibility = match visibility { + None => String::new(), + Some(it) => format!("{it} "), + }; + + ast_from_text(&format!("{visibility}enum {enum_name} {variant_list}")) +} + pub fn attr_outer(meta: ast::Meta) -> ast::Attr { ast_from_text(&format!("#[{meta}]")) } @@ -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 87fd51d703cf..8cc271d226c4 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 27c8a13e58d6..4939ab39049c 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs @@ -19,6 +19,7 @@ //! [RFC]: //! [Swift]: +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)] #[allow(unused)] @@ -74,7 +75,7 @@ pub use smol_str::SmolStr; #[derive(Debug, PartialEq, Eq)] pub struct Parse { green: GreenNode, - errors: Arc>, + errors: Arc<[SyntaxError]>, _ty: PhantomData T>, } @@ -86,7 +87,7 @@ impl Clone for Parse { impl Parse { fn new(green: GreenNode, errors: Vec) -> Parse { - Parse { green, errors: Arc::new(errors), _ty: PhantomData } + Parse { green, errors: errors.into(), _ty: PhantomData } } pub fn syntax_node(&self) -> SyntaxNode { @@ -106,7 +107,7 @@ impl Parse { T::cast(self.syntax_node()).unwrap() } - pub fn ok(self) -> Result>> { + pub fn ok(self) -> Result> { if self.errors.is_empty() { Ok(self.tree()) } else { @@ -143,7 +144,7 @@ impl Parse { parsing::incremental_reparse(self.tree().syntax(), indel, self.errors.to_vec()).map( |(green_node, errors, _reparsed_range)| Parse { green: green_node, - errors: Arc::new(errors), + errors: errors.into(), _ty: PhantomData, }, ) @@ -167,7 +168,7 @@ impl SourceFile { errors.extend(validation::validate(&root)); assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE); - Parse { green, errors: Arc::new(errors), _ty: PhantomData } + Parse { green, errors: errors.into(), _ty: PhantomData } } } @@ -181,29 +182,27 @@ impl ast::TokenTree { let kind = t.kind(); if kind.is_trivia() { was_joint = false + } else if kind == SyntaxKind::IDENT { + let token_text = t.text(); + let contextual_kw = + SyntaxKind::from_contextual_keyword(token_text).unwrap_or(SyntaxKind::IDENT); + parser_input.push_ident(contextual_kw); } else { - if kind == SyntaxKind::IDENT { - let token_text = t.text(); - let contextual_kw = SyntaxKind::from_contextual_keyword(token_text) - .unwrap_or(SyntaxKind::IDENT); - parser_input.push_ident(contextual_kw); - } else { - if was_joint { + if was_joint { + parser_input.was_joint(); + } + parser_input.push(kind); + // Tag the token as joint if it is float with a fractional part + // we use this jointness to inform the parser about what token split + // event to emit when we encounter a float literal in a field access + if kind == SyntaxKind::FLOAT_NUMBER { + if !t.text().ends_with('.') { parser_input.was_joint(); - } - parser_input.push(kind); - // Tag the token as joint if it is float with a fractional part - // we use this jointness to inform the parser about what token split - // event to emit when we encounter a float literal in a field access - if kind == SyntaxKind::FLOAT_NUMBER { - if !t.text().ends_with('.') { - parser_input.was_joint(); - } else { - was_joint = false; - } } else { - was_joint = true; + was_joint = false; } + } else { + was_joint = true; } } } @@ -276,7 +275,7 @@ impl ast::TokenTree { let (green, errors) = builder.finish_raw(); - Parse { green, errors: Arc::new(errors), _ty: PhantomData } + Parse { green, errors: errors.into(), _ty: PhantomData } } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ptr.rs b/src/tools/rust-analyzer/crates/syntax/src/ptr.rs index 1d4a89201ae4..71762996cd7d 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ptr.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ptr.rs @@ -73,6 +73,10 @@ impl AstPtr { Some(AstPtr { raw: self.raw, _ty: PhantomData }) } + pub fn kind(&self) -> parser::SyntaxKind { + self.raw.kind() + } + pub fn upcast(self) -> AstPtr where N: Into, @@ -84,6 +88,20 @@ impl AstPtr { pub fn try_from_raw(raw: SyntaxNodePtr) -> Option> { N::can_cast(raw.kind()).then_some(AstPtr { raw, _ty: PhantomData }) } + + pub fn wrap_left(self) -> AstPtr> + where + either::Either: AstNode, + { + AstPtr { raw: self.raw, _ty: PhantomData } + } + + pub fn wrap_right(self) -> AstPtr> + where + either::Either: AstNode, + { + AstPtr { raw: self.raw, _ty: PhantomData } + } } impl From> for SyntaxNodePtr { diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests.rs b/src/tools/rust-analyzer/crates/syntax/src/tests.rs index 168439053c27..3010d77d827e 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 dc6c96343d61..c2e921e4b6f3 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs @@ -622,7 +622,7 @@ fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option> { } fn lower_rule(acc: &mut Vec, grammar: &Grammar, label: Option<&String>, rule: &Rule) { - if lower_seperated_list(acc, grammar, label, rule) { + if lower_separated_list(acc, grammar, label, rule) { return; } @@ -688,7 +688,7 @@ fn lower_rule(acc: &mut Vec, grammar: &Grammar, label: Option<&String>, r } // (T (',' T)* ','?) -fn lower_seperated_list( +fn lower_separated_list( acc: &mut Vec, grammar: &Grammar, label: Option<&String>, diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs index e0ec6a242ffa..2b1bbac08e52 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 573f56b003af..cc41d87f5d97 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 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(self, optb: Option) -> Option { + pub fn and(self, _optb: Option) -> Option { loop {} } pub fn unwrap_or(self, default: T) -> T { @@ -1080,25 +1080,25 @@ pub mod option { } // endregion:result // region:fn - pub fn and_then(self, f: F) -> Option + pub fn and_then(self, _f: F) -> Option where F: FnOnce(T) -> Option, { loop {} } - pub fn unwrap_or_else(self, f: F) -> T + pub fn unwrap_or_else(self, _f: F) -> T where F: FnOnce() -> T, { loop {} } - pub fn map_or(self, default: U, f: F) -> U + pub fn map_or(self, _default: U, _f: F) -> U where F: FnOnce(T) -> U, { loop {} } - pub fn map_or_else(self, default: D, f: F) -> U + pub fn map_or_else(self, _default: D, _f: F) -> U where D: FnOnce() -> U, F: FnOnce(T) -> U, @@ -1129,7 +1129,7 @@ pub mod pin { pointer: P, } impl

    Pin

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

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

    { loop {} } } @@ -1226,7 +1226,7 @@ pub mod iter { mod sources { mod repeat { - pub fn repeat(elt: T) -> Repeat { + pub fn repeat(_elt: T) -> Repeat { loop {} } @@ -1266,7 +1266,7 @@ pub mod iter { fn take(self, n: usize) -> crate::iter::Take { loop {} } - fn filter_map(self, f: F) -> crate::iter::FilterMap + fn filter_map(self, _f: F) -> crate::iter::FilterMap where Self: Sized, F: FnMut(Self::Item) -> Option, @@ -1337,7 +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 56a68ef04379..a5f1811bf24a 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 71feed0f72ca..7c76ae81bea0 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 5dafd1a4c8c9..b605de4c7b82 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 51f0e65f4fd3..1c348b63f1a2 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 233e7bf44b16..c7b877b2897c 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": { @@ -248,6 +249,11 @@ "title": "Open Docs", "category": "rust-analyzer" }, + { + "command": "rust-analyzer.openExternalDocs", + "title": "Open External Docs", + "category": "rust-analyzer" + }, { "command": "rust-analyzer.openCargoToml", "title": "Open Cargo.toml", @@ -260,12 +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 ba8546763ec8..96e888402baf 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 245557b1e88a..7e24de664e9e 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 9821aee6f92b..987d936943a1 100644 --- a/src/tools/rust-analyzer/editors/code/src/config.ts +++ b/src/tools/rust-analyzer/editors/code/src/config.ts @@ -329,6 +329,10 @@ export class Config { get showDependenciesExplorer() { return this.get("showDependenciesExplorer"); } + + get statusBarClickAction() { + return this.get("statusBar.clickAction"); + } } // the optional `cb?` parameter is meant to be used to add additional diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts index 904efa4d5eb0..84d1ad98bd98 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 bb7896973f17..f959a76639e0 100644 --- a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts +++ b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts @@ -74,8 +74,8 @@ export interface FetchDependencyListParams {} export interface FetchDependencyListResult { crates: { - name: string | undefined; - version: string | undefined; + name?: string; + version?: string; path: string; }[]; } @@ -135,7 +135,11 @@ export const onEnter = new lc.RequestType( "experimental/openCargoToml", ); -export const openDocs = new lc.RequestType( +export interface DocsUrls { + local?: string; + web?: string; +} +export const openDocs = new lc.RequestType( "experimental/externalDocs", ); export const parentModule = new lc.RequestType< diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts index ee5e5b1b80c8..5de5aabc39f7 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 { 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 000000000000..c31ba66c50f4 --- /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 f0cd35399752..95eed3ee172c 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 471f2b5ac73e..cdd867c5f157 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 16b8ce7a916a..8a4089a56f09 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 8c2262fde811..fa941e6146ad 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 0b541b60cba9..8e3625c24491 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 3a3b26c2f63a..102155202278 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 11480e2be603..cb40c6e3a386 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 7e24793adee0..dfa386b49de7 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 7c7053aa2388..32a6ce3c719b 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 000000000000..f3f08bf116ae --- /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 000000000000..3670307ec813 --- /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 000000000000..963f087f22d4 --- /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 000000000000..e222a6dea387 --- /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 000000000000..73b1a520b06c --- /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 000000000000..4e7bc3e5154c --- /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 eb44dbd93135..797bca38ffa1 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 aca9bec77dfe..eded894c6d08 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 000000000000..d95220104c22 --- /dev/null +++ b/tests/codegen/vec-reserve-extend.rs @@ -0,0 +1,14 @@ +// compile-flags: -O + +#![crate_type = "lib"] + +// CHECK-LABEL: @should_reserve_once +#[no_mangle] +pub fn should_reserve_once(v: &mut Vec) { + // CHECK: tail call void @llvm.assume + v.try_reserve(3).unwrap(); + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}do_reserve_and_handle + // CHECK-NOT: call {{.*}}__rust_alloc( + v.extend([1, 2, 3]); +} diff --git a/tests/coverage-map/README.md b/tests/coverage-map/README.md deleted file mode 100644 index 60d1352cd64f..000000000000 --- 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 3cedb5ffbecb..000000000000 --- 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 ed3f69bdc98d..000000000000 --- 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 similarity index 100% rename from tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs rename to tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs diff --git a/tests/run-coverage-rustdoc/doctest.coverage b/tests/coverage-run-rustdoc/doctest.coverage similarity index 100% rename from tests/run-coverage-rustdoc/doctest.coverage rename to tests/coverage-run-rustdoc/doctest.coverage diff --git a/tests/run-coverage-rustdoc/doctest.rs b/tests/coverage-run-rustdoc/doctest.rs similarity index 100% rename from tests/run-coverage-rustdoc/doctest.rs rename to tests/coverage-run-rustdoc/doctest.rs diff --git a/tests/coverage/README.md b/tests/coverage/README.md new file mode 100644 index 000000000000..c72aa69c0ce0 --- /dev/null +++ b/tests/coverage/README.md @@ -0,0 +1,16 @@ +The tests in this directory are shared by two different test modes, and can be +run in multiple different ways: + +- `./x.py test coverage-map` (compiles to LLVM IR and checks coverage mappings) +- `./x.py test coverage-run` (runs a test binary and checks its coverage report) +- `./x.py test coverage` (runs both `coverage-map` and `coverage-run`) + +## Maintenance note + +These tests can be sensitive to small changes in MIR spans or MIR control flow, +especially in HIR-to-MIR lowering or MIR optimizations. + +If you haven't touched the coverage code directly, and the tests still pass in +`coverage-run` mode, then it should usually be OK to just re-bless the mappings +as necessary with `./x.py test coverage-map --bless`, without worrying too much +about the exact changes. diff --git a/tests/coverage-map/status-quo/abort.cov-map b/tests/coverage/abort.cov-map similarity index 100% rename from tests/coverage-map/status-quo/abort.cov-map rename to tests/coverage/abort.cov-map diff --git a/tests/run-coverage/abort.coverage b/tests/coverage/abort.coverage similarity index 100% rename from tests/run-coverage/abort.coverage rename to tests/coverage/abort.coverage diff --git a/tests/coverage-map/status-quo/abort.rs b/tests/coverage/abort.rs similarity index 100% rename from tests/coverage-map/status-quo/abort.rs rename to tests/coverage/abort.rs diff --git a/tests/coverage-map/status-quo/assert.cov-map b/tests/coverage/assert.cov-map similarity index 100% rename from tests/coverage-map/status-quo/assert.cov-map rename to tests/coverage/assert.cov-map diff --git a/tests/run-coverage/assert.coverage b/tests/coverage/assert.coverage similarity index 100% rename from tests/run-coverage/assert.coverage rename to tests/coverage/assert.coverage diff --git a/tests/coverage-map/status-quo/assert.rs b/tests/coverage/assert.rs similarity index 100% rename from tests/coverage-map/status-quo/assert.rs rename to tests/coverage/assert.rs diff --git a/tests/coverage-map/status-quo/async.cov-map b/tests/coverage/async.cov-map similarity index 100% rename from tests/coverage-map/status-quo/async.cov-map rename to tests/coverage/async.cov-map diff --git a/tests/run-coverage/async.coverage b/tests/coverage/async.coverage similarity index 100% rename from tests/run-coverage/async.coverage rename to tests/coverage/async.coverage diff --git a/tests/coverage-map/status-quo/async.rs b/tests/coverage/async.rs similarity index 100% rename from tests/coverage-map/status-quo/async.rs rename to tests/coverage/async.rs diff --git a/tests/coverage-map/status-quo/async2.cov-map b/tests/coverage/async2.cov-map similarity index 100% rename from tests/coverage-map/status-quo/async2.cov-map rename to tests/coverage/async2.cov-map diff --git a/tests/run-coverage/async2.coverage b/tests/coverage/async2.coverage similarity index 100% rename from tests/run-coverage/async2.coverage rename to tests/coverage/async2.coverage diff --git a/tests/coverage-map/status-quo/async2.rs b/tests/coverage/async2.rs similarity index 100% rename from tests/coverage-map/status-quo/async2.rs rename to tests/coverage/async2.rs diff --git a/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs b/tests/coverage/auxiliary/inline_always_with_dead_code.rs similarity index 100% rename from tests/run-coverage/auxiliary/inline_always_with_dead_code.rs rename to tests/coverage/auxiliary/inline_always_with_dead_code.rs diff --git a/tests/coverage/auxiliary/macro_name_span_helper.rs b/tests/coverage/auxiliary/macro_name_span_helper.rs new file mode 100644 index 000000000000..6797c081d938 --- /dev/null +++ b/tests/coverage/auxiliary/macro_name_span_helper.rs @@ -0,0 +1,10 @@ +// edition: 2021 + +#[macro_export] +macro_rules! macro_that_defines_a_function { + (fn $name:ident () $body:tt) => { + fn $name () -> () $body + } +} + +// Non-executable comment. diff --git a/tests/run-coverage/auxiliary/unused_mod_helper.rs b/tests/coverage/auxiliary/unused_mod_helper.rs similarity index 100% rename from tests/run-coverage/auxiliary/unused_mod_helper.rs rename to tests/coverage/auxiliary/unused_mod_helper.rs diff --git a/tests/run-coverage/auxiliary/used_crate.rs b/tests/coverage/auxiliary/used_crate.rs similarity index 100% rename from tests/run-coverage/auxiliary/used_crate.rs rename to tests/coverage/auxiliary/used_crate.rs diff --git a/tests/run-coverage/auxiliary/used_inline_crate.rs b/tests/coverage/auxiliary/used_inline_crate.rs similarity index 100% rename from tests/run-coverage/auxiliary/used_inline_crate.rs rename to tests/coverage/auxiliary/used_inline_crate.rs diff --git a/tests/coverage-map/status-quo/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map similarity index 100% rename from tests/coverage-map/status-quo/bad_counter_ids.cov-map rename to tests/coverage/bad_counter_ids.cov-map diff --git a/tests/run-coverage/bad_counter_ids.coverage b/tests/coverage/bad_counter_ids.coverage similarity index 100% rename from tests/run-coverage/bad_counter_ids.coverage rename to tests/coverage/bad_counter_ids.coverage diff --git a/tests/coverage-map/status-quo/bad_counter_ids.rs b/tests/coverage/bad_counter_ids.rs similarity index 100% rename from tests/coverage-map/status-quo/bad_counter_ids.rs rename to tests/coverage/bad_counter_ids.rs diff --git a/tests/coverage-map/status-quo/closure.cov-map b/tests/coverage/closure.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure.cov-map rename to tests/coverage/closure.cov-map diff --git a/tests/run-coverage/closure.coverage b/tests/coverage/closure.coverage similarity index 100% rename from tests/run-coverage/closure.coverage rename to tests/coverage/closure.coverage diff --git a/tests/coverage-map/status-quo/closure.rs b/tests/coverage/closure.rs similarity index 100% rename from tests/coverage-map/status-quo/closure.rs rename to tests/coverage/closure.rs diff --git a/tests/coverage-map/status-quo/closure_bug.cov-map b/tests/coverage/closure_bug.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure_bug.cov-map rename to tests/coverage/closure_bug.cov-map diff --git a/tests/run-coverage/closure_bug.coverage b/tests/coverage/closure_bug.coverage similarity index 100% rename from tests/run-coverage/closure_bug.coverage rename to tests/coverage/closure_bug.coverage diff --git a/tests/coverage-map/status-quo/closure_bug.rs b/tests/coverage/closure_bug.rs similarity index 100% rename from tests/coverage-map/status-quo/closure_bug.rs rename to tests/coverage/closure_bug.rs diff --git a/tests/coverage-map/status-quo/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure_macro.cov-map rename to tests/coverage/closure_macro.cov-map diff --git a/tests/run-coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage similarity index 100% rename from tests/run-coverage/closure_macro.coverage rename to tests/coverage/closure_macro.coverage diff --git a/tests/coverage-map/status-quo/closure_macro.rs b/tests/coverage/closure_macro.rs similarity index 100% rename from tests/coverage-map/status-quo/closure_macro.rs rename to tests/coverage/closure_macro.rs diff --git a/tests/coverage-map/status-quo/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map similarity index 100% rename from tests/coverage-map/status-quo/closure_macro_async.cov-map rename to tests/coverage/closure_macro_async.cov-map diff --git a/tests/run-coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage similarity index 100% rename from tests/run-coverage/closure_macro_async.coverage rename to tests/coverage/closure_macro_async.coverage diff --git a/tests/coverage-map/status-quo/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs similarity index 100% rename from tests/coverage-map/status-quo/closure_macro_async.rs rename to tests/coverage/closure_macro_async.rs diff --git a/tests/coverage-map/status-quo/conditions.cov-map b/tests/coverage/conditions.cov-map similarity index 100% rename from tests/coverage-map/status-quo/conditions.cov-map rename to tests/coverage/conditions.cov-map diff --git a/tests/run-coverage/conditions.coverage b/tests/coverage/conditions.coverage similarity index 100% rename from tests/run-coverage/conditions.coverage rename to tests/coverage/conditions.coverage diff --git a/tests/coverage-map/status-quo/conditions.rs b/tests/coverage/conditions.rs similarity index 100% rename from tests/coverage-map/status-quo/conditions.rs rename to tests/coverage/conditions.rs diff --git a/tests/coverage-map/status-quo/continue.cov-map b/tests/coverage/continue.cov-map similarity index 100% rename from tests/coverage-map/status-quo/continue.cov-map rename to tests/coverage/continue.cov-map diff --git a/tests/run-coverage/continue.coverage b/tests/coverage/continue.coverage similarity index 100% rename from tests/run-coverage/continue.coverage rename to tests/coverage/continue.coverage diff --git a/tests/coverage-map/status-quo/continue.rs b/tests/coverage/continue.rs similarity index 100% rename from tests/coverage-map/status-quo/continue.rs rename to tests/coverage/continue.rs diff --git a/tests/coverage-map/status-quo/coroutine.cov-map b/tests/coverage/coroutine.cov-map similarity index 100% rename from tests/coverage-map/status-quo/coroutine.cov-map rename to tests/coverage/coroutine.cov-map diff --git a/tests/run-coverage/coroutine.coverage b/tests/coverage/coroutine.coverage similarity index 100% rename from tests/run-coverage/coroutine.coverage rename to tests/coverage/coroutine.coverage diff --git a/tests/coverage-map/status-quo/coroutine.rs b/tests/coverage/coroutine.rs similarity index 100% rename from tests/coverage-map/status-quo/coroutine.rs rename to tests/coverage/coroutine.rs diff --git a/tests/coverage-map/status-quo/dead_code.cov-map b/tests/coverage/dead_code.cov-map similarity index 100% rename from tests/coverage-map/status-quo/dead_code.cov-map rename to tests/coverage/dead_code.cov-map diff --git a/tests/run-coverage/dead_code.coverage b/tests/coverage/dead_code.coverage similarity index 100% rename from tests/run-coverage/dead_code.coverage rename to tests/coverage/dead_code.coverage diff --git a/tests/coverage-map/status-quo/dead_code.rs b/tests/coverage/dead_code.rs similarity index 100% rename from tests/coverage-map/status-quo/dead_code.rs rename to tests/coverage/dead_code.rs diff --git a/tests/coverage-map/status-quo/drop_trait.cov-map b/tests/coverage/drop_trait.cov-map similarity index 100% rename from tests/coverage-map/status-quo/drop_trait.cov-map rename to tests/coverage/drop_trait.cov-map diff --git a/tests/run-coverage/drop_trait.coverage b/tests/coverage/drop_trait.coverage similarity index 100% rename from tests/run-coverage/drop_trait.coverage rename to tests/coverage/drop_trait.coverage diff --git a/tests/coverage-map/status-quo/drop_trait.rs b/tests/coverage/drop_trait.rs similarity index 100% rename from tests/coverage-map/status-quo/drop_trait.rs rename to tests/coverage/drop_trait.rs diff --git a/tests/coverage-map/fn_sig_into_try.cov-map b/tests/coverage/fn_sig_into_try.cov-map similarity index 100% rename from tests/coverage-map/fn_sig_into_try.cov-map rename to tests/coverage/fn_sig_into_try.cov-map diff --git a/tests/run-coverage/fn_sig_into_try.coverage b/tests/coverage/fn_sig_into_try.coverage similarity index 100% rename from tests/run-coverage/fn_sig_into_try.coverage rename to tests/coverage/fn_sig_into_try.coverage diff --git a/tests/coverage-map/fn_sig_into_try.rs b/tests/coverage/fn_sig_into_try.rs similarity index 100% rename from tests/coverage-map/fn_sig_into_try.rs rename to tests/coverage/fn_sig_into_try.rs diff --git a/tests/coverage-map/status-quo/generics.cov-map b/tests/coverage/generics.cov-map similarity index 100% rename from tests/coverage-map/status-quo/generics.cov-map rename to tests/coverage/generics.cov-map diff --git a/tests/run-coverage/generics.coverage b/tests/coverage/generics.coverage similarity index 100% rename from tests/run-coverage/generics.coverage rename to tests/coverage/generics.coverage diff --git a/tests/coverage-map/status-quo/generics.rs b/tests/coverage/generics.rs similarity index 100% rename from tests/coverage-map/status-quo/generics.rs rename to tests/coverage/generics.rs diff --git a/tests/coverage-map/status-quo/if.cov-map b/tests/coverage/if.cov-map similarity index 100% rename from tests/coverage-map/status-quo/if.cov-map rename to tests/coverage/if.cov-map diff --git a/tests/run-coverage/if.coverage b/tests/coverage/if.coverage similarity index 100% rename from tests/run-coverage/if.coverage rename to tests/coverage/if.coverage diff --git a/tests/coverage-map/status-quo/if.rs b/tests/coverage/if.rs similarity index 100% rename from tests/coverage-map/status-quo/if.rs rename to tests/coverage/if.rs diff --git a/tests/coverage-map/status-quo/if_else.cov-map b/tests/coverage/if_else.cov-map similarity index 100% rename from tests/coverage-map/status-quo/if_else.cov-map rename to tests/coverage/if_else.cov-map diff --git a/tests/run-coverage/if_else.coverage b/tests/coverage/if_else.coverage similarity index 100% rename from tests/run-coverage/if_else.coverage rename to tests/coverage/if_else.coverage diff --git a/tests/coverage-map/status-quo/if_else.rs b/tests/coverage/if_else.rs similarity index 100% rename from tests/coverage-map/status-quo/if_else.rs rename to tests/coverage/if_else.rs diff --git a/tests/coverage-map/status-quo/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map similarity index 100% rename from tests/coverage-map/status-quo/inline-dead.cov-map rename to tests/coverage/inline-dead.cov-map diff --git a/tests/run-coverage/inline-dead.coverage b/tests/coverage/inline-dead.coverage similarity index 100% rename from tests/run-coverage/inline-dead.coverage rename to tests/coverage/inline-dead.coverage diff --git a/tests/coverage-map/status-quo/inline-dead.rs b/tests/coverage/inline-dead.rs similarity index 100% rename from tests/coverage-map/status-quo/inline-dead.rs rename to tests/coverage/inline-dead.rs diff --git a/tests/coverage-map/status-quo/inline.cov-map b/tests/coverage/inline.cov-map similarity index 100% rename from tests/coverage-map/status-quo/inline.cov-map rename to tests/coverage/inline.cov-map diff --git a/tests/run-coverage/inline.coverage b/tests/coverage/inline.coverage similarity index 100% rename from tests/run-coverage/inline.coverage rename to tests/coverage/inline.coverage diff --git a/tests/coverage-map/status-quo/inline.rs b/tests/coverage/inline.rs similarity index 100% rename from tests/coverage-map/status-quo/inline.rs rename to tests/coverage/inline.rs diff --git a/tests/coverage-map/status-quo/inner_items.cov-map b/tests/coverage/inner_items.cov-map similarity index 100% rename from tests/coverage-map/status-quo/inner_items.cov-map rename to tests/coverage/inner_items.cov-map diff --git a/tests/run-coverage/inner_items.coverage b/tests/coverage/inner_items.coverage similarity index 100% rename from tests/run-coverage/inner_items.coverage rename to tests/coverage/inner_items.coverage diff --git a/tests/coverage-map/status-quo/inner_items.rs b/tests/coverage/inner_items.rs similarity index 100% rename from tests/coverage-map/status-quo/inner_items.rs rename to tests/coverage/inner_items.rs diff --git a/tests/coverage-map/status-quo/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map similarity index 100% rename from tests/coverage-map/status-quo/issue-83601.cov-map rename to tests/coverage/issue-83601.cov-map diff --git a/tests/run-coverage/issue-83601.coverage b/tests/coverage/issue-83601.coverage similarity index 100% rename from tests/run-coverage/issue-83601.coverage rename to tests/coverage/issue-83601.coverage diff --git a/tests/coverage-map/status-quo/issue-83601.rs b/tests/coverage/issue-83601.rs similarity index 100% rename from tests/coverage-map/status-quo/issue-83601.rs rename to tests/coverage/issue-83601.rs diff --git a/tests/coverage-map/status-quo/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map similarity index 100% rename from tests/coverage-map/status-quo/issue-84561.cov-map rename to tests/coverage/issue-84561.cov-map diff --git a/tests/run-coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage similarity index 100% rename from tests/run-coverage/issue-84561.coverage rename to tests/coverage/issue-84561.coverage diff --git a/tests/coverage-map/status-quo/issue-84561.rs b/tests/coverage/issue-84561.rs similarity index 100% rename from tests/coverage-map/status-quo/issue-84561.rs rename to tests/coverage/issue-84561.rs diff --git a/tests/coverage/issue-85461.cov-map b/tests/coverage/issue-85461.cov-map new file mode 100644 index 000000000000..d1c449b9a355 --- /dev/null +++ b/tests/coverage/issue-85461.cov-map @@ -0,0 +1,8 @@ +Function name: issue_85461::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 03, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 2) + diff --git a/tests/run-coverage/issue-85461.coverage b/tests/coverage/issue-85461.coverage similarity index 100% rename from tests/run-coverage/issue-85461.coverage rename to tests/coverage/issue-85461.coverage diff --git a/tests/run-coverage/issue-85461.rs b/tests/coverage/issue-85461.rs similarity index 100% rename from tests/run-coverage/issue-85461.rs rename to tests/coverage/issue-85461.rs diff --git a/tests/coverage-map/status-quo/issue-93054.cov-map b/tests/coverage/issue-93054.cov-map similarity index 100% rename from tests/coverage-map/status-quo/issue-93054.cov-map rename to tests/coverage/issue-93054.cov-map diff --git a/tests/run-coverage/issue-93054.coverage b/tests/coverage/issue-93054.coverage similarity index 100% rename from tests/run-coverage/issue-93054.coverage rename to tests/coverage/issue-93054.coverage diff --git a/tests/coverage-map/status-quo/issue-93054.rs b/tests/coverage/issue-93054.rs similarity index 100% rename from tests/coverage-map/status-quo/issue-93054.rs rename to tests/coverage/issue-93054.rs diff --git a/tests/coverage-map/status-quo/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map similarity index 100% rename from tests/coverage-map/status-quo/lazy_boolean.cov-map rename to tests/coverage/lazy_boolean.cov-map diff --git a/tests/run-coverage/lazy_boolean.coverage b/tests/coverage/lazy_boolean.coverage similarity index 100% rename from tests/run-coverage/lazy_boolean.coverage rename to tests/coverage/lazy_boolean.coverage diff --git a/tests/coverage-map/status-quo/lazy_boolean.rs b/tests/coverage/lazy_boolean.rs similarity index 100% rename from tests/coverage-map/status-quo/lazy_boolean.rs rename to tests/coverage/lazy_boolean.rs diff --git a/tests/coverage-map/long_and_wide.cov-map b/tests/coverage/long_and_wide.cov-map similarity index 100% rename from tests/coverage-map/long_and_wide.cov-map rename to tests/coverage/long_and_wide.cov-map diff --git a/tests/coverage/long_and_wide.coverage b/tests/coverage/long_and_wide.coverage new file mode 100644 index 000000000000..d7d29ca40cdd --- /dev/null +++ b/tests/coverage/long_and_wide.coverage @@ -0,0 +1,151 @@ + LL| |// compile-flags: --edition=2021 + LL| |// ignore-tidy-linelength + LL| | + LL| |// This file deliberately contains line and column numbers larger than 127, + LL| |// to verify that `coverage-dump`'s ULEB128 parser can handle them. + LL| | + LL| 1|fn main() { + LL| 1| wide_function(); + LL| 1| long_function(); + LL| 1| far_function(); + LL| 1|} + LL| | + LL| |#[rustfmt::skip] + LL| 1|fn wide_function() { /* */ (); } + LL| | + LL| 1|fn long_function() { + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1| // + LL| 1|} + LL| | + LL| 1|fn far_function() {} + diff --git a/tests/coverage-map/long_and_wide.rs b/tests/coverage/long_and_wide.rs similarity index 100% rename from tests/coverage-map/long_and_wide.rs rename to tests/coverage/long_and_wide.rs diff --git a/tests/coverage-map/status-quo/loop_break_value.cov-map b/tests/coverage/loop_break_value.cov-map similarity index 100% rename from tests/coverage-map/status-quo/loop_break_value.cov-map rename to tests/coverage/loop_break_value.cov-map diff --git a/tests/run-coverage/loop_break_value.coverage b/tests/coverage/loop_break_value.coverage similarity index 100% rename from tests/run-coverage/loop_break_value.coverage rename to tests/coverage/loop_break_value.coverage diff --git a/tests/coverage-map/status-quo/loop_break_value.rs b/tests/coverage/loop_break_value.rs similarity index 100% rename from tests/coverage-map/status-quo/loop_break_value.rs rename to tests/coverage/loop_break_value.rs diff --git a/tests/coverage-map/status-quo/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map similarity index 100% rename from tests/coverage-map/status-quo/loops_branches.cov-map rename to tests/coverage/loops_branches.cov-map diff --git a/tests/run-coverage/loops_branches.coverage b/tests/coverage/loops_branches.coverage similarity index 100% rename from tests/run-coverage/loops_branches.coverage rename to tests/coverage/loops_branches.coverage diff --git a/tests/coverage-map/status-quo/loops_branches.rs b/tests/coverage/loops_branches.rs similarity index 100% rename from tests/coverage-map/status-quo/loops_branches.rs rename to tests/coverage/loops_branches.rs diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map new file mode 100644 index 000000000000..b84628fc788c --- /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 000000000000..cadf7024657e --- /dev/null +++ b/tests/coverage/macro_name_span.coverage @@ -0,0 +1,39 @@ +$DIR/auxiliary/macro_name_span_helper.rs: + LL| |// edition: 2021 + LL| | + LL| |#[macro_export] + LL| |macro_rules! macro_that_defines_a_function { + LL| | (fn $name:ident () $body:tt) => { + LL| 1| fn $name () -> () $body + LL| | } + LL| |} + LL| | + LL| |// Non-executable comment. + +$DIR/macro_name_span.rs: + LL| |// edition: 2021 + LL| | + LL| |// Regression test for . + LL| |// Under some circumstances, the heuristics that detect macro name spans can + LL| |// get confused and produce incorrect spans beyond the bounds of the span + LL| |// being processed. + LL| | + LL| |// aux-build: macro_name_span_helper.rs + LL| |extern crate macro_name_span_helper; + LL| | + LL| 1|fn main() { + LL| 1| affected_function(); + LL| 1|} + LL| | + LL| |macro_rules! macro_with_an_unreasonably_and_egregiously_long_name { + LL| | () => { + LL| | println!("hello"); + LL| | }; + LL| |} + LL| | + LL| |macro_name_span_helper::macro_that_defines_a_function! { + LL| | fn affected_function() { + LL| | macro_with_an_unreasonably_and_egregiously_long_name!(); + LL| | } + LL| |} + diff --git a/tests/coverage/macro_name_span.rs b/tests/coverage/macro_name_span.rs new file mode 100644 index 000000000000..5d15977c498f --- /dev/null +++ b/tests/coverage/macro_name_span.rs @@ -0,0 +1,25 @@ +// edition: 2021 + +// Regression test for . +// Under some circumstances, the heuristics that detect macro name spans can +// get confused and produce incorrect spans beyond the bounds of the span +// being processed. + +// aux-build: macro_name_span_helper.rs +extern crate macro_name_span_helper; + +fn main() { + affected_function(); +} + +macro_rules! macro_with_an_unreasonably_and_egregiously_long_name { + () => { + println!("hello"); + }; +} + +macro_name_span_helper::macro_that_defines_a_function! { + fn affected_function() { + macro_with_an_unreasonably_and_egregiously_long_name!(); + } +} diff --git a/tests/coverage-map/status-quo/match_or_pattern.cov-map b/tests/coverage/match_or_pattern.cov-map similarity index 100% rename from tests/coverage-map/status-quo/match_or_pattern.cov-map rename to tests/coverage/match_or_pattern.cov-map diff --git a/tests/run-coverage/match_or_pattern.coverage b/tests/coverage/match_or_pattern.coverage similarity index 100% rename from tests/run-coverage/match_or_pattern.coverage rename to tests/coverage/match_or_pattern.coverage diff --git a/tests/coverage-map/status-quo/match_or_pattern.rs b/tests/coverage/match_or_pattern.rs similarity index 100% rename from tests/coverage-map/status-quo/match_or_pattern.rs rename to tests/coverage/match_or_pattern.rs diff --git a/tests/coverage-map/status-quo/nested_loops.cov-map b/tests/coverage/nested_loops.cov-map similarity index 100% rename from tests/coverage-map/status-quo/nested_loops.cov-map rename to tests/coverage/nested_loops.cov-map diff --git a/tests/run-coverage/nested_loops.coverage b/tests/coverage/nested_loops.coverage similarity index 100% rename from tests/run-coverage/nested_loops.coverage rename to tests/coverage/nested_loops.coverage diff --git a/tests/coverage-map/status-quo/nested_loops.rs b/tests/coverage/nested_loops.rs similarity index 100% rename from tests/coverage-map/status-quo/nested_loops.rs rename to tests/coverage/nested_loops.rs diff --git a/tests/coverage-map/status-quo/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map similarity index 100% rename from tests/coverage-map/status-quo/no_cov_crate.cov-map rename to tests/coverage/no_cov_crate.cov-map diff --git a/tests/run-coverage/no_cov_crate.coverage b/tests/coverage/no_cov_crate.coverage similarity index 100% rename from tests/run-coverage/no_cov_crate.coverage rename to tests/coverage/no_cov_crate.coverage diff --git a/tests/coverage-map/status-quo/no_cov_crate.rs b/tests/coverage/no_cov_crate.rs similarity index 100% rename from tests/coverage-map/status-quo/no_cov_crate.rs rename to tests/coverage/no_cov_crate.rs diff --git a/tests/coverage-map/status-quo/overflow.cov-map b/tests/coverage/overflow.cov-map similarity index 89% rename from tests/coverage-map/status-quo/overflow.cov-map rename to tests/coverage/overflow.cov-map index bfffd9b2ab51..39a5c05f879a 100644 --- a/tests/coverage-map/status-quo/overflow.cov-map +++ b/tests/coverage/overflow.cov-map @@ -1,5 +1,5 @@ Function name: overflow::main -Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 0f, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] +Raw bytes (65): 0x[01, 01, 08, 01, 1b, 05, 1f, 09, 0d, 03, 11, 16, 05, 03, 11, 05, 1f, 09, 0d, 09, 01, 10, 01, 01, 1b, 03, 02, 0b, 00, 18, 16, 01, 0c, 00, 1a, 05, 00, 1b, 03, 0a, 12, 03, 13, 00, 20, 09, 00, 21, 03, 0a, 0d, 03, 0a, 00, 0b, 1b, 01, 09, 00, 17, 11, 02, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -12,7 +12,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Counter(1), rhs = Expression(7, Add) - expression 7 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 9 -- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 27) +- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 27) - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 24) = (c0 + (c1 + (c2 + c3))) - Code(Expression(5, Sub)) at (prev + 1, 12) to (start + 0, 26) @@ -27,14 +27,14 @@ Number of file 0 mappings: 9 - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) Function name: overflow::might_overflow -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 04, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 07, 01, 09, 05, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 05, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 07, 01, 09, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 4, 1) to (start + 1, 18) +- Code(Counter(0)) at (prev + 5, 1) to (start + 1, 18) - Code(Counter(1)) at (prev + 1, 19) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) diff --git a/tests/run-coverage/overflow.coverage b/tests/coverage/overflow.coverage similarity index 98% rename from tests/run-coverage/overflow.coverage rename to tests/coverage/overflow.coverage index cee076e88cd4..4f8dffc0c481 100644 --- a/tests/run-coverage/overflow.coverage +++ b/tests/coverage/overflow.coverage @@ -1,4 +1,5 @@ LL| |#![allow(unused_assignments)] + LL| |// compile-flags: -Coverflow-checks=yes LL| |// failure-status: 101 LL| | LL| 4|fn might_overflow(to_add: u32) -> u32 { diff --git a/tests/coverage-map/status-quo/overflow.rs b/tests/coverage/overflow.rs similarity index 98% rename from tests/coverage-map/status-quo/overflow.rs rename to tests/coverage/overflow.rs index bbb65c1b35df..1c40771b2747 100644 --- a/tests/coverage-map/status-quo/overflow.rs +++ b/tests/coverage/overflow.rs @@ -1,4 +1,5 @@ #![allow(unused_assignments)] +// compile-flags: -Coverflow-checks=yes // failure-status: 101 fn might_overflow(to_add: u32) -> u32 { diff --git a/tests/coverage-map/status-quo/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map similarity index 100% rename from tests/coverage-map/status-quo/panic_unwind.cov-map rename to tests/coverage/panic_unwind.cov-map diff --git a/tests/run-coverage/panic_unwind.coverage b/tests/coverage/panic_unwind.coverage similarity index 100% rename from tests/run-coverage/panic_unwind.coverage rename to tests/coverage/panic_unwind.coverage diff --git a/tests/coverage-map/status-quo/panic_unwind.rs b/tests/coverage/panic_unwind.rs similarity index 100% rename from tests/coverage-map/status-quo/panic_unwind.rs rename to tests/coverage/panic_unwind.rs diff --git a/tests/coverage-map/status-quo/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map similarity index 100% rename from tests/coverage-map/status-quo/partial_eq.cov-map rename to tests/coverage/partial_eq.cov-map diff --git a/tests/run-coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage similarity index 100% rename from tests/run-coverage/partial_eq.coverage rename to tests/coverage/partial_eq.coverage diff --git a/tests/coverage-map/status-quo/partial_eq.rs b/tests/coverage/partial_eq.rs similarity index 100% rename from tests/coverage-map/status-quo/partial_eq.rs rename to tests/coverage/partial_eq.rs diff --git a/tests/coverage-map/status-quo/simple_loop.cov-map b/tests/coverage/simple_loop.cov-map similarity index 100% rename from tests/coverage-map/status-quo/simple_loop.cov-map rename to tests/coverage/simple_loop.cov-map diff --git a/tests/run-coverage/simple_loop.coverage b/tests/coverage/simple_loop.coverage similarity index 100% rename from tests/run-coverage/simple_loop.coverage rename to tests/coverage/simple_loop.coverage diff --git a/tests/coverage-map/status-quo/simple_loop.rs b/tests/coverage/simple_loop.rs similarity index 100% rename from tests/coverage-map/status-quo/simple_loop.rs rename to tests/coverage/simple_loop.rs diff --git a/tests/coverage-map/status-quo/simple_match.cov-map b/tests/coverage/simple_match.cov-map similarity index 100% rename from tests/coverage-map/status-quo/simple_match.cov-map rename to tests/coverage/simple_match.cov-map diff --git a/tests/run-coverage/simple_match.coverage b/tests/coverage/simple_match.coverage similarity index 100% rename from tests/run-coverage/simple_match.coverage rename to tests/coverage/simple_match.coverage diff --git a/tests/coverage-map/status-quo/simple_match.rs b/tests/coverage/simple_match.rs similarity index 100% rename from tests/coverage-map/status-quo/simple_match.rs rename to tests/coverage/simple_match.rs diff --git a/tests/coverage-map/status-quo/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map similarity index 70% rename from tests/coverage-map/status-quo/sort_groups.cov-map rename to tests/coverage/sort_groups.cov-map index db027f3dc324..3cbda6fbe1ab 100644 --- a/tests/coverage-map/status-quo/sort_groups.cov-map +++ b/tests/coverage/sort_groups.cov-map @@ -28,6 +28,21 @@ Number of file 0 mappings: 4 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = (c1 + (c0 - c1)) +Function name: sort_groups::generic_fn:: +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 17, 1) to (start + 1, 12) +- Code(Counter(1)) at (prev + 1, 13) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + Function name: sort_groups::generic_fn:: Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 07, 01, 01, 00, 02] Number of files: 1 @@ -44,19 +59,19 @@ Number of file 0 mappings: 4 = (c1 + (c0 - c1)) Function name: sort_groups::main -Raw bytes (28): 0x[01, 01, 02, 01, 00, 00, 02, 04, 01, 06, 01, 04, 0d, 00, 04, 0e, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 02, 02] +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 -- expression 0 operands: lhs = Counter(0), rhs = Zero -- expression 1 operands: lhs = Zero, rhs = Expression(0, Sub) +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 13) -- Code(Zero) at (prev + 4, 14) to (start + 2, 6) +- Code(Counter(0)) at (prev + 6, 1) to (start + 4, 35) +- Code(Counter(1)) at (prev + 4, 36) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) - = (c0 - Zero) + = (c0 - c1) - Code(Expression(1, Add)) at (prev + 1, 5) to (start + 2, 2) - = (Zero + (c0 - Zero)) + = (c1 + (c0 - c1)) Function name: sort_groups::other_fn Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 11] diff --git a/tests/run-coverage/sort_groups.coverage b/tests/coverage/sort_groups.coverage similarity index 97% rename from tests/run-coverage/sort_groups.coverage rename to tests/coverage/sort_groups.coverage index 8733bf48a9c8..c70d7b3b2825 100644 --- a/tests/run-coverage/sort_groups.coverage +++ b/tests/coverage/sort_groups.coverage @@ -7,7 +7,7 @@ LL| 1| let cond = std::env::args().len() > 1; LL| 1| generic_fn::<()>(cond); LL| 1| generic_fn::<&'static str>(!cond); - LL| 1| if false { + LL| 1| if std::hint::black_box(false) { LL| 0| generic_fn::(cond); LL| 1| } LL| 1| generic_fn::(cond); diff --git a/tests/coverage-map/status-quo/sort_groups.rs b/tests/coverage/sort_groups.rs similarity index 93% rename from tests/coverage-map/status-quo/sort_groups.rs rename to tests/coverage/sort_groups.rs index f89f9f3ec61f..5adbbc6a87d1 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::(cond); } generic_fn::(cond); diff --git a/tests/coverage-map/status-quo/test_harness.cov-map b/tests/coverage/test_harness.cov-map similarity index 100% rename from tests/coverage-map/status-quo/test_harness.cov-map rename to tests/coverage/test_harness.cov-map diff --git a/tests/run-coverage/test_harness.coverage b/tests/coverage/test_harness.coverage similarity index 100% rename from tests/run-coverage/test_harness.coverage rename to tests/coverage/test_harness.coverage diff --git a/tests/coverage-map/status-quo/test_harness.rs b/tests/coverage/test_harness.rs similarity index 100% rename from tests/coverage-map/status-quo/test_harness.rs rename to tests/coverage/test_harness.rs diff --git a/tests/coverage-map/status-quo/tight_inf_loop.cov-map b/tests/coverage/tight_inf_loop.cov-map similarity index 100% rename from tests/coverage-map/status-quo/tight_inf_loop.cov-map rename to tests/coverage/tight_inf_loop.cov-map diff --git a/tests/run-coverage/tight_inf_loop.coverage b/tests/coverage/tight_inf_loop.coverage similarity index 100% rename from tests/run-coverage/tight_inf_loop.coverage rename to tests/coverage/tight_inf_loop.coverage diff --git a/tests/coverage-map/status-quo/tight_inf_loop.rs b/tests/coverage/tight_inf_loop.rs similarity index 100% rename from tests/coverage-map/status-quo/tight_inf_loop.rs rename to tests/coverage/tight_inf_loop.rs diff --git a/tests/coverage-map/trivial.cov-map b/tests/coverage/trivial.cov-map similarity index 100% rename from tests/coverage-map/trivial.cov-map rename to tests/coverage/trivial.cov-map diff --git a/tests/coverage/trivial.coverage b/tests/coverage/trivial.coverage new file mode 100644 index 000000000000..4f417979ef97 --- /dev/null +++ b/tests/coverage/trivial.coverage @@ -0,0 +1,4 @@ + LL| |// compile-flags: --edition=2021 + LL| | + LL| 1|fn main() {} + diff --git a/tests/coverage-map/trivial.rs b/tests/coverage/trivial.rs similarity index 100% rename from tests/coverage-map/trivial.rs rename to tests/coverage/trivial.rs diff --git a/tests/coverage-map/status-quo/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map similarity index 100% rename from tests/coverage-map/status-quo/try_error_result.cov-map rename to tests/coverage/try_error_result.cov-map diff --git a/tests/run-coverage/try_error_result.coverage b/tests/coverage/try_error_result.coverage similarity index 100% rename from tests/run-coverage/try_error_result.coverage rename to tests/coverage/try_error_result.coverage diff --git a/tests/coverage-map/status-quo/try_error_result.rs b/tests/coverage/try_error_result.rs similarity index 100% rename from tests/coverage-map/status-quo/try_error_result.rs rename to tests/coverage/try_error_result.rs diff --git a/tests/coverage-map/unreachable.cov-map b/tests/coverage/unreachable.cov-map similarity index 100% rename from tests/coverage-map/unreachable.cov-map rename to tests/coverage/unreachable.cov-map diff --git a/tests/run-coverage/unreachable.coverage b/tests/coverage/unreachable.coverage similarity index 100% rename from tests/run-coverage/unreachable.coverage rename to tests/coverage/unreachable.coverage diff --git a/tests/coverage-map/unreachable.rs b/tests/coverage/unreachable.rs similarity index 100% rename from tests/coverage-map/unreachable.rs rename to tests/coverage/unreachable.rs diff --git a/tests/coverage-map/status-quo/unused.cov-map b/tests/coverage/unused.cov-map similarity index 100% rename from tests/coverage-map/status-quo/unused.cov-map rename to tests/coverage/unused.cov-map diff --git a/tests/run-coverage/unused.coverage b/tests/coverage/unused.coverage similarity index 100% rename from tests/run-coverage/unused.coverage rename to tests/coverage/unused.coverage diff --git a/tests/coverage-map/status-quo/unused.rs b/tests/coverage/unused.rs similarity index 100% rename from tests/coverage-map/status-quo/unused.rs rename to tests/coverage/unused.rs diff --git a/tests/coverage/unused_mod.cov-map b/tests/coverage/unused_mod.cov-map new file mode 100644 index 000000000000..241cb2610ffc --- /dev/null +++ b/tests/coverage/unused_mod.cov-map @@ -0,0 +1,16 @@ +Function name: unused_mod::main +Raw bytes (9): 0x[01, 02, 00, 01, 01, 04, 01, 02, 02] +Number of files: 1 +- file 0 => global file 2 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 4, 1) to (start + 2, 2) + +Function name: unused_mod::unused_module::never_called_function (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 02, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 2, 1) to (start + 2, 2) + diff --git a/tests/run-coverage/unused_mod.coverage b/tests/coverage/unused_mod.coverage similarity index 100% rename from tests/run-coverage/unused_mod.coverage rename to tests/coverage/unused_mod.coverage diff --git a/tests/run-coverage/unused_mod.rs b/tests/coverage/unused_mod.rs similarity index 100% rename from tests/run-coverage/unused_mod.rs rename to tests/coverage/unused_mod.rs diff --git a/tests/coverage/uses_crate.cov-map b/tests/coverage/uses_crate.cov-map new file mode 100644 index 000000000000..9c06eab70050 --- /dev/null +++ b/tests/coverage/uses_crate.cov-map @@ -0,0 +1,40 @@ +Function name: used_crate::used_from_bin_crate_and_lib_crate_generic_function::> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 27, 1) to (start + 2, 2) + +Function name: used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) + +Function name: used_crate::used_only_from_bin_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) + +Function name: used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 2) + +Function name: uses_crate::main +Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 07, 02] +Number of files: 1 +- file 0 => global file 2 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 12, 1) to (start + 7, 2) + diff --git a/tests/run-coverage/uses_crate.coverage b/tests/coverage/uses_crate.coverage similarity index 100% rename from tests/run-coverage/uses_crate.coverage rename to tests/coverage/uses_crate.coverage diff --git a/tests/run-coverage/uses_crate.rs b/tests/coverage/uses_crate.rs similarity index 100% rename from tests/run-coverage/uses_crate.rs rename to tests/coverage/uses_crate.rs diff --git a/tests/coverage/uses_inline_crate.cov-map b/tests/coverage/uses_inline_crate.cov-map new file mode 100644 index 000000000000..6b621825c886 --- /dev/null +++ b/tests/coverage/uses_inline_crate.cov-map @@ -0,0 +1,55 @@ +Function name: used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 44, 1) to (start + 2, 2) + +Function name: used_inline_crate::used_inline_function +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 14, 01, 06, 0f, 05, 06, 10, 02, 06, 02, 02, 06, 00, 07, 07, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 20, 1) to (start + 6, 15) +- Code(Counter(1)) at (prev + 6, 16) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 1, 5) to (start + 1, 2) + = (c1 + (c0 - c1)) + +Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) + +Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) + +Function name: used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> +Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 49, 1) to (start + 2, 2) + +Function name: uses_inline_crate::main +Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 0a, 02] +Number of files: 1 +- file 0 => global file 2 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 12, 1) to (start + 10, 2) + diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/coverage/uses_inline_crate.coverage similarity index 100% rename from tests/run-coverage/uses_inline_crate.coverage rename to tests/coverage/uses_inline_crate.coverage diff --git a/tests/run-coverage/uses_inline_crate.rs b/tests/coverage/uses_inline_crate.rs similarity index 100% rename from tests/run-coverage/uses_inline_crate.rs rename to tests/coverage/uses_inline_crate.rs diff --git a/tests/coverage-map/status-quo/while.cov-map b/tests/coverage/while.cov-map similarity index 100% rename from tests/coverage-map/status-quo/while.cov-map rename to tests/coverage/while.cov-map diff --git a/tests/run-coverage/while.coverage b/tests/coverage/while.coverage similarity index 100% rename from tests/run-coverage/while.coverage rename to tests/coverage/while.coverage diff --git a/tests/coverage-map/status-quo/while.rs b/tests/coverage/while.rs similarity index 100% rename from tests/coverage-map/status-quo/while.rs rename to tests/coverage/while.rs diff --git a/tests/coverage-map/status-quo/while_early_ret.cov-map b/tests/coverage/while_early_ret.cov-map similarity index 100% rename from tests/coverage-map/status-quo/while_early_ret.cov-map rename to tests/coverage/while_early_ret.cov-map diff --git a/tests/run-coverage/while_early_ret.coverage b/tests/coverage/while_early_ret.coverage similarity index 100% rename from tests/run-coverage/while_early_ret.coverage rename to tests/coverage/while_early_ret.coverage diff --git a/tests/coverage-map/status-quo/while_early_ret.rs b/tests/coverage/while_early_ret.rs similarity index 100% rename from tests/coverage-map/status-quo/while_early_ret.rs rename to tests/coverage/while_early_ret.rs diff --git a/tests/coverage-map/status-quo/yield.cov-map b/tests/coverage/yield.cov-map similarity index 100% rename from tests/coverage-map/status-quo/yield.cov-map rename to tests/coverage/yield.cov-map diff --git a/tests/run-coverage/yield.coverage b/tests/coverage/yield.coverage similarity index 100% rename from tests/run-coverage/yield.coverage rename to tests/coverage/yield.coverage diff --git a/tests/coverage-map/status-quo/yield.rs b/tests/coverage/yield.rs similarity index 100% rename from tests/coverage-map/status-quo/yield.rs rename to tests/coverage/yield.rs diff --git a/tests/debuginfo/simple-struct.rs b/tests/debuginfo/simple-struct.rs index aa3cf023a718..fea8109223ad 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 396e4a378f6f..111dd8e97f9a 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 9e442e0f98a9..a83a6c07461f 100644 --- a/tests/mir-opt/building/custom/terminators.rs +++ b/tests/mir-opt/building/custom/terminators.rs @@ -13,7 +13,7 @@ fn ident(t: T) -> T { fn direct_call(x: i32) -> i32 { mir!( { - Call(RET = ident(x), retblock) + Call(RET = ident(x), retblock, UnwindContinue()) } retblock = { @@ -27,7 +27,7 @@ fn direct_call(x: i32) -> i32 { fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 { mir!( { - Call(RET = f(x), retblock) + Call(RET = f(x), retblock, UnwindContinue()) } retblock = { @@ -49,7 +49,7 @@ impl<'a> Drop for WriteOnDrop<'a> { fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { mir!( { - Drop(a, retblock) + Drop(a, retblock, UnwindContinue()) } retblock = { @@ -64,7 +64,7 @@ fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { fn drop_second<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { mir!( { - Drop(b, retblock) + Drop(b, retblock, UnwindContinue()) } retblock = { diff --git a/tests/mir-opt/building/custom/unwind_action.rs b/tests/mir-opt/building/custom/unwind_action.rs new file mode 100644 index 000000000000..e3c4ffac358a --- /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 000000000000..efdf2ddb1d02 --- /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 1946c70e4764..b99b0b99559a 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 b6175b051568..d1d86b55d686 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 0b57d1b97e15..1d4fe67f350c 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 000000000000..b06c1639c3f3 --- /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 000000000000..26c82edf2d5f --- /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 000000000000..1bb72074846e --- /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 f5d822520a70..87c07279552f 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -4,6 +4,12 @@ fn main() -> () { let mut _0: (); let _1: u8; + let mut _5: u8; + let mut _6: u8; + let mut _7: u8; + let mut _8: u8; + let mut _14: u32; + let mut _15: u32; scope 1 { - debug x => _1; + debug x => const 1_u8; @@ -19,34 +25,23 @@ scope 4 { - debug sum => _4; + debug sum => const 6_u8; - let _5: &str; + let _9: &str; scope 5 { -- debug s => _5; +- debug s => _9; + debug s => const "hello, world!"; - let _8: bool; - let _9: bool; - let _10: u32; + let _10: (bool, bool, u32); scope 6 { -- debug ((f: (bool, bool, u32)).0: bool) => _8; -- debug ((f: (bool, bool, u32)).1: bool) => _9; -- debug ((f: (bool, bool, u32)).2: u32) => _10; -+ debug ((f: (bool, bool, u32)).0: bool) => const true; -+ debug ((f: (bool, bool, u32)).1: bool) => const false; -+ debug ((f: (bool, bool, u32)).2: u32) => const 123_u32; - let _6: std::option::Option; + debug f => _10; + let _11: std::option::Option; scope 7 { -- debug o => _6; -+ debug o => const Option::::Some(99_u16); - let _11: u32; - let _12: u32; + debug o => _11; + let _12: Point; scope 8 { -- debug ((p: Point).0: u32) => _11; -- debug ((p: Point).1: u32) => _12; -+ debug ((p: Point).0: u32) => const 32_u32; -+ debug ((p: Point).1: u32) => const 32_u32; - let _7: u32; +- debug p => _12; ++ debug p => const Point {{ x: 32_u32, y: 32_u32 }}; + let _13: u32; scope 9 { -- debug a => _7; +- debug a => _13; + debug a => const 64_u32; } } @@ -59,37 +54,57 @@ } bb0: { + StorageLive(_1); _1 = const 1_u8; + StorageLive(_2); _2 = const 2_u8; + StorageLive(_3); _3 = const 3_u8; StorageLive(_4); - _4 = const 6_u8; StorageLive(_5); - _5 = const "hello, world!"; - StorageLive(_8); - StorageLive(_9); - StorageLive(_10); - _8 = const true; - _9 = const false; - _10 = const 123_u32; StorageLive(_6); - _6 = const Option::::Some(99_u16); - _11 = const 32_u32; - _12 = const 32_u32; + _6 = const 1_u8; StorageLive(_7); - _7 = const 64_u32; + _7 = const 2_u8; + _5 = const 3_u8; StorageDead(_7); StorageDead(_6); + StorageLive(_8); + _8 = const 3_u8; + _4 = const 6_u8; StorageDead(_8); - StorageDead(_9); - StorageDead(_10); StorageDead(_5); + StorageLive(_9); + _9 = const "hello, world!"; + StorageLive(_10); + _10 = (const true, const false, const 123_u32); + StorageLive(_11); + _11 = Option::::Some(const 99_u16); + StorageLive(_12); + _12 = const Point {{ x: 32_u32, y: 32_u32 }}; + StorageLive(_13); + StorageLive(_14); + _14 = const 32_u32; + StorageLive(_15); + _15 = const 32_u32; + _13 = const 64_u32; + StorageDead(_15); + StorageDead(_14); + _0 = const (); + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); + StorageDead(_10); + StorageDead(_9); StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + StorageDead(_1); return; } } - ALLOC0 (size: 4, align: 2) { - 01 00 63 00 │ ..c. + ALLOC0 (size: 8, align: 4) { + 20 00 00 00 20 00 00 00 │ ... ... } diff --git a/tests/mir-opt/const_debuginfo.rs b/tests/mir-opt/const_debuginfo.rs index d8ae08a0723c..0e5ac4b8bd60 100644 --- a/tests/mir-opt/const_debuginfo.rs +++ b/tests/mir-opt/const_debuginfo.rs @@ -1,12 +1,23 @@ -// skip-filecheck -// compile-flags: -C overflow-checks=no -Zunsound-mir-opts +// unit-test: ConstDebugInfo +// compile-flags: -C overflow-checks=no -Zmir-enable-passes=+ConstProp struct Point { x: u32, y: u32, } +// EMIT_MIR const_debuginfo.main.ConstDebugInfo.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => const 1_u8; + // CHECK: debug y => const 2_u8; + // CHECK: debug z => const 3_u8; + // CHECK: debug sum => const 6_u8; + // CHECK: debug s => const "hello, world!"; + // CHECK: debug f => {{_.*}}; + // CHECK: debug o => {{_.*}}; + // CHECK: debug p => const Point + // CHECK: debug a => const 64_u32; let x = 1u8; let y = 2u8; let z = 3u8; @@ -21,5 +32,3 @@ fn main() { let p = Point { x: 32, y: 32 }; let a = p.x + p.y; } - -// EMIT_MIR const_debuginfo.main.ConstDebugInfo.diff diff --git a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/tests/mir-opt/const_prop/indirect_mutation.bar.ConstProp.diff similarity index 100% rename from tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff rename to tests/mir-opt/const_prop/indirect_mutation.bar.ConstProp.diff diff --git a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/tests/mir-opt/const_prop/indirect_mutation.foo.ConstProp.diff similarity index 100% rename from tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff rename to tests/mir-opt/const_prop/indirect_mutation.foo.ConstProp.diff diff --git a/tests/mir-opt/const_prop/indirect_mutation.rs b/tests/mir-opt/const_prop/indirect_mutation.rs new file mode 100644 index 000000000000..ec9da6e8e5c5 --- /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 8a5289d58991..2571c3856f46 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 00696535ac15..000000000000 --- 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 c6b8ad3571f3..a44e65164af0 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 2970f5f0b8d4..bc6760707ccc 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 2077874ee9a7..8593d9fa9aba 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 8629d535bcf7..438a90dddd0c 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 dcd15fb2b09e..b2eb64756f9a 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 8896f5ff345b..c9ad06a9da26 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 10a66ced026e..6e082acdbd39 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 2989582d0382..b4bd45ba597f 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 2989582d0382..b4bd45ba597f 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 90ec3ab49ad0..ebb2f70a4758 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 36134e019ad0..1b9c8fe15c25 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 61329bb75d13..54da6ee659f9 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 61329bb75d13..54da6ee659f9 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 3a3d451ee8d7..000000000000 --- 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 21c4b92cf045..000000000000 --- 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 21c4b92cf045..000000000000 --- 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 98264bdc1afe..000000000000 --- 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 85e6662a6adc..000000000000 --- 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 efd9e62d64e1..000000000000 --- a/tests/run-coverage/async.rs +++ /dev/null @@ -1,128 +0,0 @@ -#![allow(unused_assignments, dead_code)] - -// compile-flags: --edition=2018 -C opt-level=1 - -async fn c(x: u8) -> u8 { - if x == 8 { - 1 - } else { - 0 - } -} - -async fn d() -> u8 { 1 } - -async fn e() -> u8 { 1 } // unused function; executor does not block on `g()` - -async fn f() -> u8 { 1 } - -async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()` - -pub async fn g(x: u8) { - match x { - y if e().await == y => (), - y if f().await == y => (), - _ => (), - } -} - -async fn h(x: usize) { // The function signature is counted when called, but the body is not - // executed (not awaited) so the open brace has a `0` count (at least when - // displayed with `llvm-cov show` in color-mode). - match x { - y if foo().await[y] => (), - _ => (), - } -} - -async fn i(x: u8) { // line coverage is 1, but there are 2 regions: - // (a) the function signature, counted when the function is called; and - // (b) the open brace for the function body, counted once when the body is - // executed asynchronously. - match x { - y if c(x).await == y + 1 => { d().await; } - y if f().await == y + 1 => (), - _ => (), - } -} - -fn j(x: u8) { - // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`. - fn c(x: u8) -> u8 { - if x == 8 { - 1 // This line appears covered, but the 1-character expression span covering the `1` - // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because - // `fn j()` executes the open brace for the function body, followed by the function's - // first executable statement, `match x`. Inner function declarations are not - // "visible" to the MIR for `j()`, so the code region counts all lines between the - // open brace and the first statement as executed, which is, in a sense, true. - // `llvm-cov show` overcomes this kind of situation by showing the actual counts - // of the enclosed coverages, (that is, the `1` expression was not executed, and - // accurately displays a `0`). - } else { - 0 - } - } - fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed - fn f() -> u8 { 1 } - match x { - y if c(x) == y + 1 => { d(); } - y if f() == y + 1 => (), - _ => (), - } -} - -fn k(x: u8) { // unused function - match x { - 1 => (), - 2 => (), - _ => (), - } -} - -fn l(x: u8) { - match x { - 1 => (), - 2 => (), - _ => (), - } -} - -async fn m(x: u8) -> u8 { x - 1 } - -fn main() { - let _ = g(10); - let _ = h(9); - let mut future = Box::pin(i(8)); - j(7); - l(6); - let _ = m(5); - executor::block_on(future.as_mut()); -} - -mod executor { - use core::{ - future::Future, - pin::Pin, - task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, - }; - - pub fn block_on(mut future: F) -> F::Output { - let mut future = unsafe { Pin::new_unchecked(&mut future) }; - use std::hint::unreachable_unchecked; - static VTABLE: RawWakerVTable = RawWakerVTable::new( - |_| unsafe { unreachable_unchecked() }, // clone - |_| unsafe { unreachable_unchecked() }, // wake - |_| unsafe { unreachable_unchecked() }, // wake_by_ref - |_| (), - ); - let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; - let mut context = Context::from_waker(&waker); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/run-coverage/async2.rs b/tests/run-coverage/async2.rs deleted file mode 100644 index 2884ff297aff..000000000000 --- a/tests/run-coverage/async2.rs +++ /dev/null @@ -1,57 +0,0 @@ -// compile-flags: --edition=2018 - -fn non_async_func() { - println!("non_async_func was covered"); - let b = true; - if b { - println!("non_async_func println in block"); - } -} - -async fn async_func() { - println!("async_func was covered"); - let b = true; - if b { - println!("async_func println in block"); - } -} - -async fn async_func_just_println() { - println!("async_func_just_println was covered"); -} - -fn main() { - println!("codecovsample::main"); - - non_async_func(); - - executor::block_on(async_func()); - executor::block_on(async_func_just_println()); -} - -mod executor { - use core::{ - future::Future, - pin::Pin, - task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, - }; - - pub fn block_on(mut future: F) -> F::Output { - let mut future = unsafe { Pin::new_unchecked(&mut future) }; - use std::hint::unreachable_unchecked; - static VTABLE: RawWakerVTable = RawWakerVTable::new( - |_| unsafe { unreachable_unchecked() }, // clone - |_| unsafe { unreachable_unchecked() }, // wake - |_| unsafe { unreachable_unchecked() }, // wake_by_ref - |_| (), - ); - let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; - let mut context = Context::from_waker(&waker); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/run-coverage/bad_counter_ids.rs b/tests/run-coverage/bad_counter_ids.rs deleted file mode 100644 index ef5460102b70..000000000000 --- a/tests/run-coverage/bad_counter_ids.rs +++ /dev/null @@ -1,66 +0,0 @@ -#![feature(coverage_attribute)] -// compile-flags: --edition=2021 -Copt-level=0 -Zmir-opt-level=3 - -// Regression test for . -// -// If some coverage counters were removed by MIR optimizations, we need to take -// care not to refer to those counter IDs in coverage mappings, and instead -// replace them with a constant zero value. If we don't, `llvm-cov` might see -// a too-large counter ID and silently discard the entire function from its -// coverage reports. - -#[derive(Debug, PartialEq, Eq)] -struct Foo(u32); - -fn eq_good() { - println!("a"); - assert_eq!(Foo(1), Foo(1)); -} - -fn eq_good_message() { - println!("b"); - assert_eq!(Foo(1), Foo(1), "message b"); -} - -fn ne_good() { - println!("c"); - assert_ne!(Foo(1), Foo(3)); -} - -fn ne_good_message() { - println!("d"); - assert_ne!(Foo(1), Foo(3), "message d"); -} - -fn eq_bad() { - println!("e"); - assert_eq!(Foo(1), Foo(3)); -} - -fn eq_bad_message() { - println!("f"); - assert_eq!(Foo(1), Foo(3), "message f"); -} - -fn ne_bad() { - println!("g"); - assert_ne!(Foo(1), Foo(1)); -} - -fn ne_bad_message() { - println!("h"); - assert_ne!(Foo(1), Foo(1), "message h"); -} - -#[coverage(off)] -fn main() { - eq_good(); - eq_good_message(); - ne_good(); - ne_good_message(); - - assert!(std::panic::catch_unwind(eq_bad).is_err()); - assert!(std::panic::catch_unwind(eq_bad_message).is_err()); - assert!(std::panic::catch_unwind(ne_bad).is_err()); - assert!(std::panic::catch_unwind(ne_bad_message).is_err()); -} diff --git a/tests/run-coverage/closure.rs b/tests/run-coverage/closure.rs deleted file mode 100644 index 16a2c4e33bd4..000000000000 --- a/tests/run-coverage/closure.rs +++ /dev/null @@ -1,220 +0,0 @@ -#![allow(unused_assignments, unused_variables)] -// compile-flags: -C opt-level=2 - -// This test used to be sensitive to certain coverage-specific hacks in -// `rustc_middle/mir/mono.rs`, but those hacks were later cleaned up by -// . - -fn main() { - // Initialize test constants in a way that cannot be determined at compile time, to ensure - // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from - // dependent conditions. - let is_true = std::env::args().len() == 1; - let is_false = !is_true; - - let mut some_string = Some(String::from("the string content")); - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 1".to_owned() - } - ) - ); - - some_string = Some(String::from("the string content")); - let - a - = - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 2".to_owned() - }; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - a - ) - ); - - some_string = None; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 3".to_owned() - } - ) - ); - - some_string = None; - let - a - = - || - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - "alt string 4".to_owned() - }; - println!( - "The string or alt: {}" - , - some_string - . - unwrap_or_else - ( - a - ) - ); - - let - quote_closure - = - |val| - { - let mut countdown = 0; - if is_false { - countdown = 10; - } - format!("'{}'", val) - }; - println!( - "Repeated, quoted string: {:?}" - , - std::iter::repeat("repeat me") - .take(5) - .map - ( - quote_closure - ) - .collect::>() - ); - - let - _unused_closure - = - | - mut countdown - | - { - if is_false { - countdown = 10; - } - "closure should be unused".to_owned() - }; - - let mut countdown = 10; - let _short_unused_closure = | _unused_arg: u8 | countdown += 1; - - - let short_used_covered_closure_macro = | used_arg: u8 | println!("called"); - let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called"); - let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called"); - - - - - let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") }; - - let _shortish_unused_closure = | _unused_arg: u8 | { - println!("not called") - }; - - let _as_short_unused_closure = | - _unused_arg: u8 - | { println!("not called") }; - - let _almost_as_short_unused_closure = | - _unused_arg: u8 - | { println!("not called") } - ; - - - - - - let _short_unused_closure_line_break_no_block = | _unused_arg: u8 | -println!("not called") - ; - - let _short_unused_closure_line_break_no_block2 = - | _unused_arg: u8 | - println!( - "not called" - ) - ; - - let short_used_not_covered_closure_line_break_no_block_embedded_branch = - | _unused_arg: u8 | - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - ; - - let short_used_not_covered_closure_line_break_block_embedded_branch = - | _unused_arg: u8 | - { - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - } - ; - - let short_used_covered_closure_line_break_no_block_embedded_branch = - | _unused_arg: u8 | - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - ; - - let short_used_covered_closure_line_break_block_embedded_branch = - | _unused_arg: u8 | - { - println!( - "not called: {}", - if is_true { "check" } else { "me" } - ) - } - ; - - if is_false { - short_used_not_covered_closure_macro(0); - short_used_not_covered_closure_line_break_no_block_embedded_branch(0); - short_used_not_covered_closure_line_break_block_embedded_branch(0); - } - short_used_covered_closure_macro(0); - short_used_covered_closure_line_break_no_block_embedded_branch(0); - short_used_covered_closure_line_break_block_embedded_branch(0); -} diff --git a/tests/run-coverage/closure_bug.rs b/tests/run-coverage/closure_bug.rs deleted file mode 100644 index 739bc5f0b51c..000000000000 --- 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 9b289141c2e5..000000000000 --- a/tests/run-coverage/closure_macro.rs +++ /dev/null @@ -1,40 +0,0 @@ -// compile-flags: --edition=2018 -#![feature(coverage_attribute)] - -macro_rules! bail { - ($msg:literal $(,)?) => { - if $msg.len() > 0 { - println!("no msg"); - } else { - println!($msg); - } - return Err(String::from($msg)); - }; -} - -macro_rules! on_error { - ($value:expr, $error_message:expr) => { - $value.or_else(|e| { // FIXME(85000): no coverage in closure macros - let message = format!($error_message, e); - if message.len() > 0 { - println!("{}", message); - Ok(String::from("ok")) - } else { - bail!("error"); - } - }) - }; -} - -fn load_configuration_files() -> Result { - Ok(String::from("config")) -} - -pub fn main() -> Result<(), String> { - println!("Starting service"); - let config = on_error!(load_configuration_files(), "Error loading configs: {}")?; - - let startup_delay_duration = String::from("arg"); - let _ = (config, startup_delay_duration); - Ok(()) -} diff --git a/tests/run-coverage/closure_macro_async.rs b/tests/run-coverage/closure_macro_async.rs deleted file mode 100644 index b4275599e599..000000000000 --- a/tests/run-coverage/closure_macro_async.rs +++ /dev/null @@ -1,77 +0,0 @@ -// compile-flags: --edition=2018 -#![feature(coverage_attribute)] - -macro_rules! bail { - ($msg:literal $(,)?) => { - if $msg.len() > 0 { - println!("no msg"); - } else { - println!($msg); - } - return Err(String::from($msg)); - }; -} - -macro_rules! on_error { - ($value:expr, $error_message:expr) => { - $value.or_else(|e| { // FIXME(85000): no coverage in closure macros - let message = format!($error_message, e); - if message.len() > 0 { - println!("{}", message); - Ok(String::from("ok")) - } else { - bail!("error"); - } - }) - }; -} - -fn load_configuration_files() -> Result { - Ok(String::from("config")) -} - -pub async fn test() -> Result<(), String> { - println!("Starting service"); - let config = on_error!(load_configuration_files(), "Error loading configs: {}")?; - - let startup_delay_duration = String::from("arg"); - let _ = (config, startup_delay_duration); - Ok(()) -} - -#[coverage(off)] -fn main() { - executor::block_on(test()).unwrap(); -} - -mod executor { - use core::{ - future::Future, - pin::Pin, - task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, - }; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = unsafe { Pin::new_unchecked(&mut future) }; - use std::hint::unreachable_unchecked; - static VTABLE: RawWakerVTable = RawWakerVTable::new( - #[coverage(off)] - |_| unsafe { unreachable_unchecked() }, // clone - #[coverage(off)] - |_| unsafe { unreachable_unchecked() }, // wake - #[coverage(off)] - |_| unsafe { unreachable_unchecked() }, // wake_by_ref - #[coverage(off)] - |_| (), - ); - let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; - let mut context = Context::from_waker(&waker); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/run-coverage/conditions.rs b/tests/run-coverage/conditions.rs deleted file mode 100644 index fa7f2a116c21..000000000000 --- 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 624aa98341b8..000000000000 --- 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 86d19af6f4f0..000000000000 --- a/tests/run-coverage/coroutine.rs +++ /dev/null @@ -1,30 +0,0 @@ -#![feature(coroutines, coroutine_trait)] - -use std::ops::{Coroutine, CoroutineState}; -use std::pin::Pin; - -// The following implementation of a function called from a `yield` statement -// (apparently requiring the Result and the `String` type or constructor) -// creates conditions where the `coroutine::StateTransform` MIR transform will -// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic -// to handle this condition, and still report dead block coverage. -fn get_u32(val: bool) -> Result { - if val { Ok(1) } else { Err(String::from("some error")) } -} - -fn main() { - let is_true = std::env::args().len() == 1; - let mut coroutine = || { - yield get_u32(is_true); - return "foo"; - }; - - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Yielded(Ok(1)) => {} - _ => panic!("unexpected return from resume"), - } - match Pin::new(&mut coroutine).resume(()) { - CoroutineState::Complete("foo") => {} - _ => panic!("unexpected return from resume"), - } -} diff --git a/tests/run-coverage/dead_code.rs b/tests/run-coverage/dead_code.rs deleted file mode 100644 index 3492712a6f98..000000000000 --- 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 7b062719c6b0..000000000000 --- 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 92850c8a188f..000000000000 --- a/tests/run-coverage/fn_sig_into_try.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![feature(coverage_attribute)] -// compile-flags: --edition=2021 - -// Regression test for inconsistent handling of function signature spans that -// are followed by code using the `?` operator. -// -// For each of these similar functions, the line containing the function -// signature should be handled in the same way. - -fn a() -> Option -{ - Some(7i32); - Some(0) -} - -fn b() -> Option -{ - Some(7i32)?; - Some(0) -} - -fn c() -> Option -{ - let _ = Some(7i32)?; - Some(0) -} - -fn d() -> Option -{ - let _: () = (); - Some(7i32)?; - Some(0) -} - -#[coverage(off)] -fn main() { - a(); - b(); - c(); - d(); -} diff --git a/tests/run-coverage/generics.rs b/tests/run-coverage/generics.rs deleted file mode 100644 index bf4c2d8d6853..000000000000 --- a/tests/run-coverage/generics.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 1 - -struct Firework where T: Copy + std::fmt::Display { - strength: T, -} - -impl Firework where T: Copy + std::fmt::Display { - #[inline(always)] - fn set_strength(&mut self, new_strength: T) { - self.strength = new_strength; - } -} - -impl Drop for Firework where T: Copy + std::fmt::Display { - #[inline(always)] - fn drop(&mut self) { - println!("BOOM times {}!!!", self.strength); - } -} - -fn main() -> Result<(), u8> { - let mut firecracker = Firework { strength: 1 }; - firecracker.set_strength(2); - - let mut tnt = Firework { strength: 100.1 }; - tnt.set_strength(200.1); - tnt.set_strength(300.3); - - if true { - println!("Exiting with error..."); - return Err(1); - } - - let _ = Firework { strength: 1000 }; - - Ok(()) -} - -// Expected program output: -// Exiting with error... -// BOOM times 100!!! -// BOOM times 1!!! -// Error: 1 diff --git a/tests/run-coverage/if.rs b/tests/run-coverage/if.rs deleted file mode 100644 index 8ad5042ff7ba..000000000000 --- 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 3244e1e3afd2..000000000000 --- 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 854fa0629675..000000000000 --- a/tests/run-coverage/inline-dead.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Regression test for issue #98833. -// compile-flags: -Zinline-mir -Cdebug-assertions=off - -fn main() { - println!("{}", live::()); - - let f = |x: bool| { - debug_assert!( - x - ); - }; - f(false); -} - -#[inline] -fn live() -> u32 { - if B { - dead() - } else { - 0 - } -} - -#[inline] -fn dead() -> u32 { - 42 -} diff --git a/tests/run-coverage/inline.rs b/tests/run-coverage/inline.rs deleted file mode 100644 index 9cfab9ddbadf..000000000000 --- a/tests/run-coverage/inline.rs +++ /dev/null @@ -1,51 +0,0 @@ -// compile-flags: -Zinline-mir - -use std::fmt::Display; - -fn main() { - permutations(&['a', 'b', 'c']); -} - -#[inline(always)] -fn permutations(xs: &[T]) { - let mut ys = xs.to_owned(); - permutate(&mut ys, 0); -} - -fn permutate(xs: &mut [T], k: usize) { - let n = length(xs); - if k == n { - display(xs); - } else if k < n { - for i in k..n { - swap(xs, i, k); - permutate(xs, k + 1); - swap(xs, i, k); - } - } else { - error(); - } -} - -fn length(xs: &[T]) -> usize { - xs.len() -} - -#[inline] -fn swap(xs: &mut [T], i: usize, j: usize) { - let t = xs[i]; - xs[i] = xs[j]; - xs[j] = t; -} - -fn display(xs: &[T]) { - for x in xs { - print!("{}", x); - } - println!(); -} - -#[inline(always)] -fn error() { - panic!("error"); -} diff --git a/tests/run-coverage/inner_items.rs b/tests/run-coverage/inner_items.rs deleted file mode 100644 index bcb62b3031cd..000000000000 --- 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 0b72a81947cc..000000000000 --- 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 facf5b5b4cfb..000000000000 --- 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 da546cfeef85..000000000000 --- a/tests/run-coverage/issue-93054.rs +++ /dev/null @@ -1,30 +0,0 @@ -#![allow(dead_code, unreachable_code)] - -// Regression test for #93054: Functions using uninhabited types often only have a single, -// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail. -// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them. - -// compile-flags: --edition=2021 - -enum Never {} - -impl Never { - fn foo(self) { - match self {} - make().map(|never| match never {}); - } - - fn bar(&self) { - match *self {} - } -} - -async fn foo2(never: Never) { - match never {} -} - -fn make() -> Option { - None -} - -fn main() {} diff --git a/tests/run-coverage/lazy_boolean.rs b/tests/run-coverage/lazy_boolean.rs deleted file mode 100644 index bb6219e851c8..000000000000 --- 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 dbc4fad7a231..000000000000 --- 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 f3a343bcc1f4..000000000000 --- 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 ab7aee51d1bc..000000000000 --- 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 4c7c78427965..000000000000 --- 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 e12e4bc55e3e..000000000000 --- 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 bbb65c1b35df..000000000000 --- 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 638d2eb6aaaf..000000000000 --- 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 dd8b42c18cea..000000000000 --- 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 6f7f23475b82..000000000000 --- 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 be99e59a8268..000000000000 --- 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 f89f9f3ec61f..000000000000 --- 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::(cond); - } - generic_fn::(cond); - other_fn(); -} - -fn generic_fn(cond: bool) { - if cond { - println!("{}", std::any::type_name::()); - } -} - -fn other_fn() {} diff --git a/tests/run-coverage/test_harness.rs b/tests/run-coverage/test_harness.rs deleted file mode 100644 index 12a755734c19..000000000000 --- 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 cef99027aaa4..000000000000 --- 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 557cbf22bfad..000000000000 --- a/tests/run-coverage/try_error_result.rs +++ /dev/null @@ -1,118 +0,0 @@ -#![allow(unused_assignments)] -// failure-status: 1 - -fn call(return_error: bool) -> Result<(), ()> { - if return_error { - Err(()) - } else { - Ok(()) - } -} - -fn test1() -> Result<(), ()> { - let mut - countdown = 10 - ; - for - _ - in - 0..10 - { - countdown - -= 1 - ; - if - countdown < 5 - { - call(/*return_error=*/ true)?; - call(/*return_error=*/ false)?; - } - else - { - call(/*return_error=*/ false)?; - } - } - Ok(()) -} - -struct Thing1; -impl Thing1 { - fn get_thing_2(&self, return_error: bool) -> Result { - if return_error { - Err(()) - } else { - Ok(Thing2 {}) - } - } -} - -struct Thing2; -impl Thing2 { - fn call(&self, return_error: bool) -> Result { - if return_error { - Err(()) - } else { - Ok(57) - } - } -} - -fn test2() -> Result<(), ()> { - let thing1 = Thing1{}; - let mut - countdown = 10 - ; - for - _ - in - 0..10 - { - countdown - -= 1 - ; - if - countdown < 5 - { - thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail"); - thing1 - . - get_thing_2(/*return_error=*/ false) - ? - . - call(/*return_error=*/ true) - . - expect_err( - "call should fail" - ); - let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?; - assert_eq!(val, 57); - let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?; - assert_eq!(val, 57); - } - else - { - let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?; - assert_eq!(val, 57); - let val = thing1 - .get_thing_2(/*return_error=*/ false)? - .call(/*return_error=*/ false)?; - assert_eq!(val, 57); - let val = thing1 - .get_thing_2(/*return_error=*/ false) - ? - .call(/*return_error=*/ false) - ? - ; - assert_eq!(val, 57); - } - } - Ok(()) -} - -fn main() -> Result<(), ()> { - test1().expect_err("test1 should fail"); - test2() - ? - ; - Ok(()) -} diff --git a/tests/run-coverage/unreachable.rs b/tests/run-coverage/unreachable.rs deleted file mode 100644 index 6385bfa160d7..000000000000 --- a/tests/run-coverage/unreachable.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![feature(core_intrinsics)] -#![feature(coverage_attribute)] -// compile-flags: --edition=2021 - -// -// If we instrument a function for coverage, but all of its counter-increment -// statements are removed by MIR optimizations, LLVM will think it isn't -// instrumented and it will disappear from coverage maps and coverage reports. -// Most MIR opts won't cause this because they tend not to remove statements -// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends -// with `TerminatorKind::Unreachable`. - -use std::hint::{black_box, unreachable_unchecked}; - -static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() }; - -fn unreachable_function() { - unsafe { unreachable_unchecked() } -} - -// Use an intrinsic to more reliably trigger unreachable-propagation. -fn unreachable_intrinsic() { - unsafe { std::intrinsics::unreachable() } -} - -#[coverage(off)] -fn main() { - if black_box(false) { - UNREACHABLE_CLOSURE(); - } - if black_box(false) { - unreachable_function(); - } - if black_box(false) { - unreachable_intrinsic(); - } -} diff --git a/tests/run-coverage/unused.rs b/tests/run-coverage/unused.rs deleted file mode 100644 index d985af135470..000000000000 --- a/tests/run-coverage/unused.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![allow(dead_code, unused_assignments, unused_must_use, unused_variables)] - -fn foo(x: T) { - let mut i = 0; - while i < 10 { - i != 0 || i != 0; - i += 1; - } -} - -fn unused_template_func(x: T) { - let mut i = 0; - while i < 10 { - i != 0 || i != 0; - i += 1; - } -} - -fn unused_func(mut a: u32) { - if a != 0 { - a += 1; - } -} - -fn unused_func2(mut a: u32) { - if a != 0 { - a += 1; - } -} - -fn unused_func3(mut a: u32) { - if a != 0 { - a += 1; - } -} - -fn main() -> Result<(), u8> { - foo::(0); - foo::(0.0); - Ok(()) -} diff --git a/tests/run-coverage/while.rs b/tests/run-coverage/while.rs deleted file mode 100644 index 781b90b35663..000000000000 --- 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 b2f0eee2cc0f..000000000000 --- 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 b7e2ba31b59c..000000000000 --- 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 0d2c6b2209bd..e2ce66c99e4c 100644 --- a/tests/rustdoc-json/doc_hidden_failure.rs +++ b/tests/rustdoc-json/doc_hidden_failure.rs @@ -1,8 +1,5 @@ // Regression test for . -#![feature(no_core)] -#![no_core] - mod auto { mod action_row { pub struct ActionRowBuilder; diff --git a/tests/rustdoc-json/enums/field_hidden.rs b/tests/rustdoc-json/enums/field_hidden.rs index f24098580579..74d96248d5c7 100644 --- a/tests/rustdoc-json/enums/field_hidden.rs +++ b/tests/rustdoc-json/enums/field_hidden.rs @@ -1,11 +1,5 @@ // Regression test for . -#![no_core] -#![feature(no_core, lang_items)] - -#[lang = "sized"] -trait Sized {} - // @has "$.index[*][?(@.name=='ParseError')]" // @has "$.index[*][?(@.name=='UnexpectedEndTag')]" // @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.kind.tuple" [null] diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs index 777161c4e4ba..68483683464b 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 34a4f4aec538..53cdf83ffa68 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 49990ec53315..bec89530b052 100644 --- a/tests/rustdoc-json/enums/use_glob.rs +++ b/tests/rustdoc-json/enums/use_glob.rs @@ -1,8 +1,5 @@ // Regression test for -#![feature(no_core)] -#![no_core] - // @set Color = "$.index[*][?(@.name == 'Color')].id" pub enum Color { Red, diff --git a/tests/rustdoc-json/enums/use_variant.rs b/tests/rustdoc-json/enums/use_variant.rs index 8190e1cbe81d..c7e0c21f1ef4 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 3b82561ec7df..8b3a8c0a74eb 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 d6ea343b9911..eef9ae99eb02 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 539d17f831eb..2f6cf3bf65a1 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 27d842066f4e..8e82efef4beb 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 5239a6f21f53..44dc6d854aa3 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 9cfe649243f8..56d6e7a49dbd 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 f37ce0abb414..7de1ed78f2ff 100644 --- a/tests/rustdoc-json/glob_import.rs +++ b/tests/rustdoc-json/glob_import.rs @@ -1,13 +1,10 @@ // This is a regression test for . -#![feature(no_core)] #![no_std] -#![no_core] // @has "$.index[*][?(@.name=='glob')]" // @has "$.index[*][?(@.inner.import)].inner.import.name" \"*\" - mod m1 { pub fn f() {} } diff --git a/tests/rustdoc-json/impls/impl_item_visibility.rs b/tests/rustdoc-json/impls/impl_item_visibility.rs index efa54d91dcaa..d3c15cd23e44 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 3c6fefc4ca29..fa3a36df8563 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 b98d1e4167ce..7c68a2412f36 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 d2b0665dcafa..3da03df2546c 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 d2ac316d47d4..7857626d66ed 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 fcd27ca4b7c5..836f1fe87da3 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 141c54a57dd1..97db9c93a0f2 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 37a720003295..015e89c22810 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 769dd3f0a2c0..acc3a879fe1c 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 dc28258a8b67..419b0b4fcab1 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 6e105b382b00..549e4c200dca 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 b8279298c1e7..917e9e0790c9 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 cabee0b1caa5..d925fcd52215 100644 --- a/tests/rustdoc-json/non_lifetime_binders.rs +++ b/tests/rustdoc-json/non_lifetime_binders.rs @@ -3,18 +3,9 @@ #![feature(non_lifetime_binders)] #![allow(incomplete_features)] -#![no_core] -#![feature(lang_items, no_core)] - -#[lang = "sized"] -pub trait Sized {} - pub trait Trait {} -#[lang = "phantom_data"] -struct PhantomData; - -pub struct Wrapper(PhantomData); +pub struct Wrapper(std::marker::PhantomData); // @count "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[*]" 2 // @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\" diff --git a/tests/rustdoc-json/primitives/primitive_overloading.rs b/tests/rustdoc-json/primitives/primitive_overloading.rs index 81e0acdc6e93..50e23fc06d3e 100644 --- a/tests/rustdoc-json/primitives/primitive_overloading.rs +++ b/tests/rustdoc-json/primitives/primitive_overloading.rs @@ -3,14 +3,10 @@ // Regression test for . #![feature(rustc_attrs)] -#![feature(no_core)] - -#![no_core] // @has "$.index[*][?(@.name=='usize')]" // @has "$.index[*][?(@.name=='prim')]" #[rustc_doc_primitive = "usize"] /// This is the built-in type `usize`. -mod prim { -} +mod prim {} diff --git a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs index 37ca279b352c..a8f5500d6297 100644 --- a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs +++ b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs @@ -1,8 +1,5 @@ //! Regression test for -#![feature(no_core)] -#![no_core] - #![crate_name = "export_extern_crate_as_self"] // ignore-tidy-linelength diff --git a/tests/rustdoc-json/reexport/glob_collision.rs b/tests/rustdoc-json/reexport/glob_collision.rs index dee35ba78dc4..9a75f4c0cf38 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 78edfaf0aa8d..ed0c4a420d48 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 ae4e87d23bc5..11ea5aa3522b 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 f81445bd48da..a4133e2f0c7d 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 c5c41b25f7ec..37f7b26fc859 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 ac0632b98a95..be09cb47629d 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 1c49f213d1a7..bc072be81a31 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 8c8152bd16c3..d7b766235578 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 cdcbf2a2bc86..e6f037eb4b38 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 a2a25d08448a..15d194ef5d92 100644 --- a/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs +++ b/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs @@ -1,15 +1,13 @@ // Regression test for -#![feature(no_core)] -#![no_core] - mod repeat_n { #[doc(hidden)] + /// not here pub struct RepeatN {} } +/// not here pub use repeat_n::RepeatN; // @count "$.index[*][?(@.name=='pub_use_doc_hidden')].inner.items[*]" 0 -// @!has "$.index[*][?(@.kind=='struct')]" -// @!has "$.index[*][?(@.kind=='import')]" +// @!has "$.index[*][?(@.docs == 'not here')]" diff --git a/tests/rustdoc-json/reexport/reexport_of_hidden.rs b/tests/rustdoc-json/reexport/reexport_of_hidden.rs new file mode 100644 index 000000000000..1b6ff5fadca1 --- /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 9114460231dc..3924282a49e5 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 d0fd314bd8c9..636937874483 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 6a765b733016..42ba6c40019a 100644 --- a/tests/rustdoc-json/reexport/same_name_different_types.rs +++ b/tests/rustdoc-json/reexport/same_name_different_types.rs @@ -1,8 +1,5 @@ // Regression test for . -#![feature(no_core)] -#![no_core] - pub mod nested { // @set foo_struct = "$.index[*][?(@.docs == 'Foo the struct')].id" diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs index a00547dc3481..1e1710e1c086 100644 --- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs +++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs @@ -2,9 +2,7 @@ // Regression test for . -#![feature(no_core)] #![no_std] -#![no_core] mod inner { // @set trait_id = "$.index[*][?(@.name=='Trait')].id" diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs index 462efee51bf4..2ca8c7fa6be6 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 1373f96f87f0..04611eeb95ca 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 0ce81b5e59fa..a9301b3fe4f3 100644 --- a/tests/rustdoc-json/return_private.rs +++ b/tests/rustdoc-json/return_private.rs @@ -1,9 +1,6 @@ // Regression test for . // ignore-tidy-linelength -#![feature(no_core)] -#![no_core] - mod secret { pub struct Secret; } diff --git a/tests/rustdoc-json/stripped_modules.rs b/tests/rustdoc-json/stripped_modules.rs index d2664b49e9c2..d5ab1173d924 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 7d351ad61be2..c27553c75448 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 49238e5e88be..67b5a858ab76 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 2123ac40427e..bbae3557cf9c 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 64c6c53ce472..f86031479519 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 13788df0fc99..0ddb3dc92150 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 f50a9b96d812..b6379c05a859 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 000000000000..b0c21ffaeb99 --- /dev/null +++ b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs @@ -0,0 +1,16 @@ +#![feature(effects, const_trait_impl)] + +#[const_trait] +pub trait Resource {} + +pub const fn load() -> i32 { + 0 +} + +pub const fn lock() {} + +#[allow(non_upper_case_globals)] +pub trait Clash {} + +#[allow(non_upper_case_globals)] +pub const fn clash, const host: u64>() {} diff --git a/tests/rustdoc/inline_cross/auxiliary/const-fn.rs b/tests/rustdoc/inline_cross/auxiliary/const-fn.rs deleted file mode 100644 index 26332b419b6d..000000000000 --- 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 000000000000..1d003e28f36d --- /dev/null +++ b/tests/rustdoc/inline_cross/const-effect-param.rs @@ -0,0 +1,29 @@ +// Regression test for issue #116629. +// Check that we don't render host effect parameters & arguments. + +// aux-crate:const_effect_param=const-effect-param.rs +// edition: 2021 +#![crate_name = "user"] + +// Don't render the host param on `load` and the host arg `host` passed to `Resource`. +// @has user/fn.load.html +// @has - '//pre[@class="rust item-decl"]' "pub const fn load() -> i32\ +// where \ +// R: Resource" +pub use const_effect_param::load; + +// Don't render the host arg `true` passed to `Resource`. +// @has user/fn.lock.html +// @has - '//pre[@class="rust item-decl"]' "pub const fn lock()\ +// where \ +// R: Resource" +pub use const_effect_param::lock; + +// Regression test for an issue introduced in PR #116670. +// Don't hide the const param `host` since it actually isn't the host effect param. +// @has user/fn.clash.html +// @has - '//pre[@class="rust item-decl"]' \ +// "pub const fn clash()\ +// where \ +// T: Clash" +pub use const_effect_param::clash; diff --git a/tests/rustdoc/inline_cross/const-fn.rs b/tests/rustdoc/inline_cross/const-fn.rs deleted file mode 100644 index 24934b873c25..000000000000 --- 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 000000000000..2916c7a84a1f --- /dev/null +++ b/tests/rustdoc/issue-115295-macro-const-display.rs @@ -0,0 +1,40 @@ +#![crate_name = "foo"] + +// @has foo/trait.Trait.html +pub trait Trait {} + +// @has foo/struct.WithConst.html +pub struct WithConst; + +macro_rules! spans_from_macro { + () => { + impl WithConst<42> { + pub fn new() -> Self { + Self + } + } + impl Trait> for WithConst<42> {} + impl Trait> for WithConst<{ 43 }> {} + impl Trait> for WithConst<44> {} + pub struct Other { + pub field: WithConst<42>, + } + }; +} + +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<41>" +impl Trait> for WithConst<41> {} + +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl WithConst<42>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<42>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<{ 43 }>" +// @has - '//*[@class="impl"]//h3[@class="code-header"]' \ +// "impl Trait> for WithConst<44>" + +// @has foo/struct.Other.html +// @has - //pre "pub field: WithConst<42>" +spans_from_macro!(); diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs index 3d6cff00a6d2..685a029dcb22 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)) { 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 963460c11824..c9941d1c5a00 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 a51dc88a4ede..524d778c09b8 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 f40154e16f34..7c6811d81eea 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 f23d17d6bfa5..49b112f9313d 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 d1ebca8a29e9..c15d19b1594d 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 000000000000..f579eb6772d4 --- /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 000000000000..3bba74badbce --- /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 000000000000..0c30931a1b50 --- /dev/null +++ b/tests/ui/auto-traits/issue-117789.rs @@ -0,0 +1,7 @@ +#![deny(suspicious_auto_trait_impls)] + +auto trait Trait

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

    Trait

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

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

    {} + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #13231 for more information + = help: add `#![feature(auto_traits)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0567, E0658. +For more information about an error, try `rustc --explain E0567`. diff --git a/tests/ui/binop/binary-op-suggest-deref.fixed b/tests/ui/binop/binary-op-suggest-deref.fixed new file mode 100644 index 000000000000..1ff3599137b1 --- /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 000000000000..12505a9ac27e --- /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 000000000000..1b7e45c77249 --- /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 000000000000..b47372c90648 --- /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 000000000000..14671de7e511 --- /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 000000000000..fca042b1c57d --- /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 914ebbe26a57..106485e04eea 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 000000000000..c83ba41976bc --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr @@ -0,0 +1,12 @@ +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/match-edge-cases_1.rs:29:13 + | +LL | NUMBER_POINTER => (), + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr index 0807f4590298..85426dd9a5ea 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 b4fd423becd9..32b5f5c92c52 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 3c03b03deee3..66c4f0f9cd65 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 174103eeba4c..eb8b8ac75343 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; 2] = [no_copy(); 2]; | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array - = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 for more information help: consider annotating `Bar` with `#[derive(Copy)]` | LL + #[derive(Copy)] LL | struct Bar; | +help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position + | +LL ~ const ARRAY_REPEAT_VALUE: Option = no_copy(); +LL ~ let _: [Option; 2] = [ARRAY_REPEAT_VALUE; 2]; + | error: aborting due to previous error diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 06fa4b0b1f30..858ffa820e21 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` to implement `Copy` LL | #[derive(Copy, Clone)] | ^^^^ unsatisfied trait bound introduced in this `derive` macro = note: the `Copy` trait is required because this value will be copied for each element of the array - = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 for more information = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position + | +LL ~ const ARRAY_REPEAT_VALUE: Foo = Foo(String::new()); +LL ~ [ARRAY_REPEAT_VALUE; 4]; + | error: aborting due to previous error diff --git a/tests/ui/consts/const-fn-in-vec.rs b/tests/ui/consts/const-fn-in-vec.rs index a40290eca097..0483800efefd 100644 --- a/tests/ui/consts/const-fn-in-vec.rs +++ b/tests/ui/consts/const-fn-in-vec.rs @@ -1,7 +1,11 @@ +static _MAYBE_STRINGS: [Option; 5] = [None; 5]; +//~^ ERROR the trait bound `String: Copy` is not satisfied + fn main() { // should hint to create an inline `const` block // or to create a new `const` item - let strings: [String; 5] = [String::new(); 5]; + let _strings: [String; 5] = [String::new(); 5]; + //~^ ERROR the trait bound `String: Copy` is not satisfied + let _maybe_strings: [Option; 5] = [None; 5]; //~^ ERROR the trait bound `String: Copy` is not satisfied - println!("{:?}", strings); } diff --git a/tests/ui/consts/const-fn-in-vec.stderr b/tests/ui/consts/const-fn-in-vec.stderr index 9eb7524b5044..4593034bfaea 100644 --- a/tests/ui/consts/const-fn-in-vec.stderr +++ b/tests/ui/consts/const-fn-in-vec.stderr @@ -1,13 +1,47 @@ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/const-fn-in-vec.rs:4:33 + --> $DIR/const-fn-in-vec.rs:1:47 | -LL | let strings: [String; 5] = [String::new(); 5]; - | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` +LL | static _MAYBE_STRINGS: [Option; 5] = [None; 5]; + | ^^^^ the trait `Copy` is not implemented for `String` + | + = note: required for `Option` to implement `Copy` + = note: the `Copy` trait is required because this value will be copied for each element of the array + = help: create an inline `const` block, see RFC #2920 for more information +help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position + | +LL + const ARRAY_REPEAT_VALUE: Option = None; +LL ~ static _MAYBE_STRINGS: [Option; 5] = [ARRAY_REPEAT_VALUE; 5]; + | + +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/const-fn-in-vec.rs:7:34 + | +LL | let _strings: [String; 5] = [String::new(); 5]; + | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | = note: the `Copy` trait is required because this value will be copied for each element of the array - = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];` = help: create an inline `const` block, see RFC #2920 for more information +help: consider creating a new `const` item and initializing it with the result of the 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: aborting due to previous error +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/const-fn-in-vec.rs:9:48 + | +LL | let _maybe_strings: [Option; 5] = [None; 5]; + | ^^^^ the trait `Copy` is not implemented for `String` + | + = note: required for `Option` to implement `Copy` + = note: the `Copy` trait is required because this value will be copied for each element of the array + = help: create an inline `const` block, see RFC #2920 for more information +help: consider creating a new `const` item and initializing it with the result of the constructor to be used in the repeat position + | +LL ~ const ARRAY_REPEAT_VALUE: Option = None; +LL ~ let _maybe_strings: [Option; 5] = [ARRAY_REPEAT_VALUE; 5]; + | + +error: aborting due to 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 000000000000..2491071d1e1d --- /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 000000000000..ab53346b5eed --- /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 +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:18:9 + | +LL | C_INNER => {} + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs: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 + +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 96e8795e52d5..aaf1edb6fe6e 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 731ef509ccad..441aeecbc6d9 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 98d943470a7f..000000000000 --- 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 95bed5b151ea..e0aeae667350 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 000000000000..ccf9ce8b49e1 --- /dev/null +++ b/tests/ui/coroutine/witness-ignore-fake-reads.rs @@ -0,0 +1,34 @@ +// check-pass +// edition: 2021 + +// regression test for #117059 +struct SendNotSync(*const ()); +unsafe impl Send for SendNotSync {} +// impl !Sync for SendNotSync {} // automatically disabled + +struct Inner { + stream: SendNotSync, + state: bool, +} + +struct SendSync; +impl std::ops::Deref for SendSync { + type Target = Inner; + fn deref(&self) -> &Self::Target { + todo!(); + } +} + +async fn next() { + let inner = SendSync; + match inner.state { + true if false => {} + false => async {}.await, + _ => {} + } +} + +fn is_send(_: T) {} +fn main() { + is_send(next()) +} diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.rs b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs new file mode 100644 index 000000000000..ffeb02d78b84 --- /dev/null +++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs @@ -0,0 +1,96 @@ +// Check that deriving builtin traits for a packed struct with +// non-Copy fields emits move errors along with an additional +// diagnostic note explaining the reason +// See issue #117406 + +use std::fmt::{Debug, Formatter, Result}; +use std::cmp::Ordering; + +// Packed + derives: additional diagnostic should be emitted +// for each of Debug, PartialEq and PartialOrd +#[repr(packed)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] +struct StructA(String); +//~^ ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `other` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `other` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `other` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a shared reference + + +// Unrelated impl: additinal diagnostic should NOT be emitted +impl StructA { + fn fmt(&self) -> String { + self.0 //~ ERROR: cannot move out of `self` which is behind a shared reference + } +} + +// Packed + manual impls: additional diagnostic should NOT be emitted +#[repr(packed)] +struct StructB(String); + +impl Debug for StructB { + fn fmt(&self, f: &mut Formatter) -> Result { + let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference + write!(f, "{}", x) + } +} + +impl PartialEq for StructB { + fn eq(&self, other: &StructB) -> bool { + ({ self.0 }) == ({ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +impl PartialOrd for StructB { + fn partial_cmp(&self, other: &StructB) -> Option { + PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +// NOT packed + derives: additinal diagnostic should NOT be emitted +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)] +struct StructC(String); + +// NOT packed + manual impls: additinal dignostic should NOT be emitted +struct StructD(String); + +impl Debug for StructD { + fn fmt(&self, f: &mut Formatter) -> Result { + let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference + write!(f, "{}", x) + } +} + +impl PartialEq for StructD { + fn eq(&self, other: &StructD) -> bool { + ({ self.0 }) == ({ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +impl PartialOrd for StructD { + fn partial_cmp(&self, other: &StructD) -> Option { + PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) + //~^ ERROR: cannot move out of `self` which is behind a shared reference + //~| ERROR: cannot move out of `other` which is behind a shared reference + } +} + +// Packed + derives but the move is outside of a derive +// expansion: additinal diagnostic should NOT be emitted +fn func(arg: &StructA) -> String { + arg.0 //~ ERROR: cannot move out of `arg` which is behind a shared reference +} + +fn main(){ +} diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr new file mode 100644 index 000000000000..c538061b365e --- /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 0cfe03869af1..bb1fab343a3e 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 3d9f8129d939..42154c3c3be2 100644 --- a/tests/ui/deriving/deriving-all-codegen.stdout +++ b/tests/ui/deriving/deriving-all-codegen.stdout @@ -33,6 +33,7 @@ impl ::core::clone::Clone for Empty { impl ::core::marker::Copy for Empty { } #[automatically_derived] impl ::core::fmt::Debug for Empty { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, "Empty") } @@ -97,6 +98,7 @@ impl ::core::clone::Clone for Point { impl ::core::marker::Copy for Point { } #[automatically_derived] impl ::core::fmt::Debug for Point { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x", &self.x, "y", &&self.y) @@ -183,6 +185,7 @@ impl ::core::clone::Clone for PackedPoint { impl ::core::marker::Copy for PackedPoint { } #[automatically_derived] impl ::core::fmt::Debug for PackedPoint { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field2_finish(f, "PackedPoint", "x", &{ self.x }, "y", &&{ self.y }) @@ -276,6 +279,7 @@ impl ::core::clone::Clone for Big { impl ::core::marker::Copy for Big { } #[automatically_derived] impl ::core::fmt::Debug for Big { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { let names: &'static _ = &["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"]; @@ -475,6 +479,7 @@ impl Copy for PackedManualCopy {} struct Unsized([u32]); #[automatically_derived] impl ::core::fmt::Debug for Unsized { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Unsized", &&self.0) @@ -527,6 +532,7 @@ impl ::core::cmp::Ord for Unsized { struct PackedUnsizedU8([u8]); #[automatically_derived] impl ::core::fmt::Debug for PackedUnsizedU8 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field1_finish(f, "PackedUnsizedU8", &&self.0) @@ -569,6 +575,7 @@ impl #[automatically_derived] impl ::core::fmt::Debug for Generic where T::A: ::core::fmt::Debug { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field3_finish(f, "Generic", "t", &self.t, "ta", &self.ta, "u", &&self.u) @@ -687,6 +694,7 @@ impl ::core::fmt::Debug for PackedGeneric where T::A: ::core::fmt::Debug + ::core::marker::Copy { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field3_finish(f, "PackedGeneric", &{ self.0 }, &{ self.1 }, &&{ self.2 }) @@ -797,6 +805,7 @@ impl ::core::clone::Clone for Enum0 { impl ::core::marker::Copy for Enum0 { } #[automatically_derived] impl ::core::fmt::Debug for Enum0 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match *self {} } @@ -856,6 +865,7 @@ impl ::core::clone::Clone for Enum1 { } #[automatically_derived] impl ::core::fmt::Debug for Enum1 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Enum1::Single { x: __self_0 } => @@ -932,6 +942,7 @@ impl ::core::clone::Clone for Fieldless1 { } #[automatically_derived] impl ::core::fmt::Debug for Fieldless1 { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, "A") } @@ -995,6 +1006,7 @@ impl ::core::clone::Clone for Fieldless { impl ::core::marker::Copy for Fieldless { } #[automatically_derived] impl ::core::fmt::Debug for Fieldless { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, match self { @@ -1083,6 +1095,7 @@ impl ::core::clone::Clone for Mixed { impl ::core::marker::Copy for Mixed { } #[automatically_derived] impl ::core::fmt::Debug for Mixed { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Mixed::P => ::core::fmt::Formatter::write_str(f, "P"), @@ -1217,6 +1230,7 @@ impl ::core::clone::Clone for Fielded { } #[automatically_derived] impl ::core::fmt::Debug for Fielded { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Fielded::X(__self_0) => @@ -1341,6 +1355,7 @@ impl ::core::marker::Copy #[automatically_derived] impl ::core::fmt::Debug for EnumGeneric { + #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { EnumGeneric::One(__self_0) => diff --git a/tests/ui/error-codes/E0004.stderr b/tests/ui/error-codes/E0004.stderr index 603bc5237ea2..ced478d65eae 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 eb61c4cf159a..8af0eedc82b1 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 000000000000..e19dcf9f6a54 --- /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 000000000000..893f78702375 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr @@ -0,0 +1,37 @@ +error[E0573]: expected type, found variant `Alpha::One` + --> $DIR/feature-gate-offset-of-enum.rs:11:16 + | +LL | offset_of!(Alpha::One, 0); + | ^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `Alpha` + +error[E0658]: using enums in offset_of is experimental + --> $DIR/feature-gate-offset-of-enum.rs:12:23 + | +LL | offset_of!(Alpha, One); + | ^^^ + | + = note: see issue #106655 for more information + = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable + +error[E0795]: `One` is an enum variant; expected field at end of `offset_of` + --> $DIR/feature-gate-offset-of-enum.rs:12:23 + | +LL | offset_of!(Alpha, One); + | ^^^ enum variant + +error[E0658]: using enums in offset_of is experimental + --> $DIR/feature-gate-offset-of-enum.rs:14:23 + | +LL | offset_of!(Alpha, Two.0); + | ^^^ + | + = note: see issue #106655 for more information + = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0573, E0658, E0795. +For more information about an error, try `rustc --explain E0573`. diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs index 7b1687072397..e2d51c6649ab 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 000000000000..abad0f25c0f4 --- /dev/null +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `::Bar<()>: Eq` is not satisfied + --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:30 + | +LL | type Bar: Baz = i32; + | ^^^ the trait `Eq` is not implemented for `::Bar<()>` + | +note: required for `i32` to implement `Baz` + --> $DIR/assume-gat-normalization-for-nested-goals.rs:13:23 + | +LL | impl Baz for i32 where T::Bar<()>: Eq {} + | ^^^^^^ ^^^ ------- unsatisfied trait bound introduced here +note: required by a bound in `Foo::Bar` + --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:18 + | +LL | type Bar: Baz = i32; + | ^^^^^^^^^ required by this bound in `Foo::Bar` +help: consider further restricting the associated type + | +LL | trait Foo where ::Bar<()>: Eq { + | +++++++++++++++++++++++++++++++++++++ + +error: aborting due to 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 000000000000..5ef9437c9687 --- /dev/null +++ b/tests/ui/generic-associated-types/higher-ranked-self-impl-requirement.rs @@ -0,0 +1,20 @@ +// check-pass + +trait Database: for<'r> HasValueRef<'r, Database = Self> {} + +trait HasValueRef<'r> { + type Database: Database; +} + +struct Any; + +impl Database for Any {} + +impl<'r> HasValueRef<'r> for Any { + // Make sure we don't have issues when the GAT assumption + // `>::Database = Any` isn't universally + // parameterized over `'r`. + type Database = Any; +} + +fn main() {} diff --git a/tests/ui/generic-const-items/const-trait-impl.rs b/tests/ui/generic-const-items/const-trait-impl.rs index d30f7af170dc..43cdf818c469 100644 --- a/tests/ui/generic-const-items/const-trait-impl.rs +++ b/tests/ui/generic-const-items/const-trait-impl.rs @@ -7,8 +7,8 @@ #![allow(incomplete_features)] #![crate_type = "lib"] -// FIXME(generic_const_items): Interpret `~const` as always-const. -const CREATE: T = T::create(); +// FIXME(generic_const_items, effects): Introduce `const` bounds to make this work. +const CREATE: T = T::create(); pub const K0: i32 = CREATE::; pub const K1: i32 = CREATE; // arg inferred diff --git a/tests/ui/generic-const-items/const-trait-impl.stderr b/tests/ui/generic-const-items/const-trait-impl.stderr index 34360c581d53..64aa8adf8a76 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 `::create` in constants - --> $DIR/const-trait-impl.rs:11:37 + --> $DIR/const-trait-impl.rs:11:30 | -LL | const CREATE: T = T::create(); - | ^^^^^^^^^^^ +LL | const CREATE: T = T::create(); + | ^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 1fd61084130a..e0dc13c0c95c 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 000000000000..af6ffe833945 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/async-and-ret-ref.rs @@ -0,0 +1,11 @@ +// edition:2021 +// https://github.com/rust-lang/rust/issues/117547 + +trait T {} + +trait MyTrait { + async fn foo() -> &'static impl T; + //~^ ERROR the associated type `::{opaque#0}` may not live long enough +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr b/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr new file mode 100644 index 000000000000..7c9028a8cd53 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/async-and-ret-ref.stderr @@ -0,0 +1,14 @@ +error[E0310]: the associated type `::{opaque#0}` may not live long enough + --> $DIR/async-and-ret-ref.rs:7:5 + | +LL | async fn foo() -> &'static impl T; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the associated type `::{opaque#0}` must be valid for the static lifetime... + | ...so that the reference type `&'static impl T` does not outlive the data it points at + | + = help: consider adding an explicit lifetime bound `::{opaque#0}: 'static`... + +error: aborting due to 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 6ea6bb600e94..3041c2c99a10 100644 --- a/tests/ui/indexing/indexing-requires-a-uint.stderr +++ b/tests/ui/indexing/indexing-requires-a-uint.stderr @@ -8,6 +8,8 @@ LL | [0][0u8]; = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `[{integer}]` to implement `Index` + = note: 1 redundant requirement hidden + = note: required for `[{integer}; 1]` to implement `Index` error[E0308]: mismatched types --> $DIR/indexing-requires-a-uint.rs:12:18 diff --git a/tests/ui/indexing/point-at-index-for-obligation-failure.rs b/tests/ui/indexing/point-at-index-for-obligation-failure.rs new file mode 100644 index 000000000000..e9c429b53ced --- /dev/null +++ b/tests/ui/indexing/point-at-index-for-obligation-failure.rs @@ -0,0 +1,7 @@ +fn main() { + let a = std::collections::HashMap::::new(); + let s = "hello"; + let _b = a[ + &s //~ ERROR E0277 + ]; +} diff --git a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr new file mode 100644 index 000000000000..3e2fbc2ab6f2 --- /dev/null +++ b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `String: Borrow<&str>` is not satisfied + --> $DIR/point-at-index-for-obligation-failure.rs:5:9 + | +LL | &s + | ^^ the trait `Borrow<&str>` is not implemented for `String` + | + = help: the trait `Borrow` is implemented for `String` + = help: for that trait implementation, expected `str`, found `&str` + = note: required for `HashMap` to implement `Index<&&str>` + +error: aborting due to 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 000000000000..be017a3f94fb --- /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 f1bbd4a62109..70ca00285c49 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 7b8bdfe0053a..40be39ec0774 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 a9e9c679fdb6..ccdd9a95451b 100644 --- a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr @@ -29,10 +29,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-blanket-impl.rs:33:8 @@ -52,9 +52,9 @@ LL | const CONST: usize = 2; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::CONST; +LL | ::CONST; | ~~~~~~~~~~ -LL | ::CONST; +LL | ::CONST; | ~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr index 901bfc30a3f2..4172120770c6 100644 --- a/tests/ui/methods/disambiguate-multiple-impl.stderr +++ b/tests/ui/methods/disambiguate-multiple-impl.stderr @@ -29,10 +29,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-impl.rs:34:16 diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr index 0f9c60ce243d..2778f254a561 100644 --- a/tests/ui/methods/disambiguate-multiple-trait-2.stderr +++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr @@ -37,12 +37,12 @@ LL | fn foo(&self); | ^^^^^^^^^^^^^^ help: disambiguate the method for candidate #1 | -LL | A::foo(t); - | ~~~~~~~~~ +LL | A::foo(&t); + | ~~~~~~~~~~ help: disambiguate the method for candidate #2 | -LL | B::foo(t); - | ~~~~~~~~~ +LL | B::foo(&t); + | ~~~~~~~~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-trait-2.rs:20:16 @@ -62,10 +62,10 @@ LL | const CONST: usize; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | let _ = A::CONST; - | ~~~ -LL | let _ = B::CONST; - | ~~~ +LL | let _ = ::CONST; + | ~~~~~~~~~~ +LL | let _ = ::CONST; + | ~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/disambiguate-multiple-trait-2.rs:52:12 @@ -98,10 +98,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-trait-2.rs:49:16 @@ -121,9 +121,9 @@ LL | const CONST: usize = 1; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ error: aborting due to 6 previous errors diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr index 9a50d51245ba..e00498ca62b4 100644 --- a/tests/ui/methods/disambiguate-multiple-trait.stderr +++ b/tests/ui/methods/disambiguate-multiple-trait.stderr @@ -29,10 +29,10 @@ LL | fn foo(&self) {} | ^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | ::foo(&s); - | ~~~~~~~~~~ -LL | ::foo(&s); - | ~~~~~~~~~~ +LL | A::foo(&s); + | ~~~ +LL | B::foo(&s); + | ~~~ error[E0034]: multiple applicable items in scope --> $DIR/disambiguate-multiple-trait.rs:27:16 @@ -52,9 +52,9 @@ LL | const CONST: usize = 2; | ^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax to disambiguate | -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ -LL | let _ = ::CONST; +LL | let _ = ::CONST; | ~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr index 601e6bbb006f..9a84768a9f4a 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 4e83e4b77f10..755179650bba 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 similarity index 64% rename from tests/ui/mir/addrof_alignment.rs rename to tests/ui/mir/alignment/addrof_alignment.rs index 892638bfb92b..f3423e97a8a0 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::().add(1).cast::(); + 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 similarity index 85% rename from tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs rename to tests/ui/mir/alignment/i686-pc-windows-msvc.rs index 56388c1047e9..74ba1fde6499 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::(); + let ptr = x.as_mut_ptr(); unsafe { - let misaligned = ptr.add(4).cast::(); + 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 similarity index 75% rename from tests/ui/mir/mir_alignment_check.rs rename to tests/ui/mir/alignment/misaligned_lhs.rs index d1bf3d46a7c7..97644ba8e094 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::(); + let ptr = x.as_mut_ptr(); unsafe { - *(ptr.add(1).cast::()) = 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 000000000000..8534bc71a3a2 --- /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 000000000000..754698591e33 --- /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 000000000000..fdd4864250ac --- /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 000000000000..b4be7a50f61d --- /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 000000000000..29af21dffc19 --- /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 000000000000..1787f80c07e5 --- /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 000000000000..3d18c249afe2 --- /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 000000000000..6132a6691dea --- /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 000000000000..0a1c4528aa6d --- /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 000000000000..e80d09bc90a5 --- /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 000000000000..2a74668370d4 --- /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 b3cb7813e19c..a8f6559e4253 100644 --- a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) i32)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) i32)), (), ] diff --git a/tests/ui/nll/closure-requirements/escape-argument.stderr b/tests/ui/nll/closure-requirements/escape-argument.stderr index 4f0156728ac1..40f04bb6da67 100644 --- a/tests/ui/nll/closure-requirements/escape-argument.stderr +++ b/tests/ui/nll/closure-requirements/escape-argument.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) mut &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)), (), ] 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 ccf56bf6f37d..ef2cb4067d7e 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, _outlives3, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?3 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&'?2 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?3 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?4 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr index a16433c9d374..db48a4ce70cb 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 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 9e0f16c0fc78..5ce3dae5a33d 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -6,7 +6,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case1::{closure#0} with closure args [ i32, - for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), (), ] @@ -36,7 +36,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case2::{closure#0} with closure args [ i32, - for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>)), (), ] = note: number of external vids: 2 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index e4989e321550..ffd526d90afa 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?2 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 be35e62d0704..726d0dc2a4c7 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&'?2 &ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr index 8880dd816a1f..5a65c7684485 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 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 47774b63f818..0dd53f81ae13 100644 --- a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?2 u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) u32>, std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index 3404bb128278..f7a0ee9b18d2 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?2 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 e40648912e3c..fa9fa9e8f3c7 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) &'?1 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) &'?2 u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) u32>, &ReBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon }) std::cell::Cell<&ReBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon }) u32>)), (), ] = note: late-bound region is '?3 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 18fb7195d021..35e4a16c8daf 100644 --- a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -6,7 +6,7 @@ LL | expect_sig(|a, b| b); // ought to return `a` | = note: defining type: test::{closure#0} with closure args [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, + for extern "rust-call" fn((&ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) i32)) -> &ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon }) i32, (), ] 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 000000000000..5227ca8ec17d --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -0,0 +1,40 @@ +error[E0597]: `a` does not live long enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 + | +LL | let b = |_| &a; + | --- -^ + | | || + | | |borrowed value does not live long enough + | | returning this value requires that `a` is borrowed for `'static` + | value captured here +... +LL | } + | - `a` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/location-insensitive-scopes-issue-117146.rs:20:22 + | +LL | fn bad &()>(_: F) {} + | ^^^ + +error: implementation of `Fn` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `Fn` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` + +error: implementation of `FnOnce` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr new file mode 100644 index 000000000000..5227ca8ec17d --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -0,0 +1,40 @@ +error[E0597]: `a` does not live long enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 + | +LL | let b = |_| &a; + | --- -^ + | | || + | | |borrowed value does not live long enough + | | returning this value requires that `a` is borrowed for `'static` + | value captured here +... +LL | } + | - `a` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/location-insensitive-scopes-issue-117146.rs:20:22 + | +LL | fn bad &()>(_: F) {} + | ^^^ + +error: implementation of `Fn` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `Fn` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` + +error: implementation of `FnOnce` is not general enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs new file mode 100644 index 000000000000..c165e7a1d1a5 --- /dev/null +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs @@ -0,0 +1,20 @@ +// This is a non-regression test for issue #117146, where NLL and `-Zpolonius=next` computed +// different loan scopes when a region flowed into an SCC whose representative was an existential +// region. + +// revisions: nll polonius +// [polonius] compile-flags: -Zpolonius=next + +fn main() { + let a = (); + let b = |_| &a; + //[nll]~^ ERROR `a` does not live long enough + //[polonius]~^^ ERROR `a` does not live long enough + bad(&b); + //[nll]~^ ERROR implementation of `Fn` + //[nll]~| ERROR implementation of `FnOnce` + //[polonius]~^^^ ERROR implementation of `Fn` + //[polonius]~| ERROR implementation of `FnOnce` +} + +fn bad &()>(_: F) {} diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 59e29e9a420f..0048eef6779e 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -6,7 +6,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic::::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), + for extern "rust-call" fn((std::option::Option>, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), (), ] = note: number of external vids: 2 @@ -28,7 +28,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic_fail::::{closure#0} with closure args [ i16, - for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), + for extern "rust-call" fn((std::option::Option>, &ReBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon }) T)), (), ] = note: late-bound region is '?2 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 000000000000..475b41388d3b --- /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 e8b5a08377bd..a2d6aace47da 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 6fa30d63fb86..b7affdb79439 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 000000000000..1f34c73a2c3b --- /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 000000000000..7182d86d001d --- /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 e645b68ba87c..8250dd1ea2e9 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 000000000000..eaae288864a3 --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +pub fn func() where F: FnOnce() -> () {} +//~^ ERROR expected one of +//~| NOTE expected one of +//~| NOTE `Fn` bounds require arguments in parentheses + +fn main() {} diff --git a/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs new file mode 100644 index 000000000000..ea5c71150e83 --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.rs @@ -0,0 +1,8 @@ +// run-rustfix + +pub fn func() where F: FnOnce -> () {} +//~^ ERROR expected one of +//~| NOTE expected one of +//~| NOTE `Fn` bounds require arguments in parentheses + +fn main() {} diff --git a/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr new file mode 100644 index 000000000000..7cda667570de --- /dev/null +++ b/tests/ui/parser/issues/issue-108109-fn-trait-missing-paren.stderr @@ -0,0 +1,11 @@ +error: expected one of `(`, `+`, `,`, `::`, `<`, or `{`, found `->` + --> $DIR/issue-108109-fn-trait-missing-paren.rs:3:34 + | +LL | pub fn func() where F: FnOnce -> () {} + | -------^^ expected one of `(`, `+`, `,`, `::`, `<`, or `{` + | | | + | | help: try adding parentheses + | `Fn` bounds require arguments in parentheses + +error: aborting due to 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 df0cd54399a5..099178a7d50f 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 977c6ebfef35..4c55179ce237 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 000000000000..9d7fe43893e7 --- /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 000000000000..3f504a9ebfc4 --- /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 bbebc99e94b8..479426626858 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 f455caba158c..489e8eefb052 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 4ff4cf5c8ca8..867f71c12040 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 2f5fbc513ee3..9a7f28210f93 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 df2412e3e9b3..8305ff4f6238 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 000000000000..9c21af0372d2 --- /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 000000000000..c1a8f92965eb --- /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 b3c17ce8974d..dee4b3f557c7 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 000000000000..0b3e7ce9e9a0 --- /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 000000000000..679fc83e7f56 --- /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 6dc1425cf037..27e305a39724 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.rs +++ b/tests/ui/pattern/usefulness/consts-opaque.rs @@ -95,8 +95,10 @@ fn main() { const QUUX: Quux = quux; match QUUX { - QUUX => {} - QUUX => {} + QUUX => {} //~WARN behave unpredictably + //~| previously accepted + QUUX => {} //~WARN behave unpredictably + //~| previously accepted _ => {} } @@ -105,14 +107,17 @@ fn main() { const WRAPQUUX: Wrap = Wrap(quux); match WRAPQUUX { - WRAPQUUX => {} - WRAPQUUX => {} + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} } match WRAPQUUX { Wrap(_) => {} - WRAPQUUX => {} + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted } match WRAPQUUX { @@ -121,7 +126,8 @@ fn main() { match WRAPQUUX { //~^ ERROR: non-exhaustive patterns: `Wrap(_)` not covered - WRAPQUUX => {} + WRAPQUUX => {} //~WARN behave unpredictably + //~| previously accepted } #[derive(PartialEq, Eq)] @@ -132,9 +138,11 @@ fn main() { const WHOKNOWSQUUX: WhoKnows = WhoKnows::Yay(quux); match WHOKNOWSQUUX { - WHOKNOWSQUUX => {} + WHOKNOWSQUUX => {} //~WARN behave unpredictably + //~| previously accepted WhoKnows::Yay(_) => {} - WHOKNOWSQUUX => {} + WHOKNOWSQUUX => {} //~WARN behave unpredictably + //~| previously accepted WhoKnows::Nope => {} } } diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index 51f2f276bbe2..09f72ba927e1 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -91,24 +91,96 @@ LL | BAZ => {} = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:98:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:100:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:110:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:112:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:119:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:129:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:141:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:144:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + error[E0004]: non-exhaustive patterns: `Wrap(_)` not covered - --> $DIR/consts-opaque.rs:122:11 + --> $DIR/consts-opaque.rs:127:11 | LL | match WRAPQUUX { | ^^^^^^^^ pattern `Wrap(_)` not covered | note: `Wrap usize>` defined here - --> $DIR/consts-opaque.rs:104:12 + --> $DIR/consts-opaque.rs:106:12 | LL | struct Wrap(T); | ^^^^ = note: the matched value is of type `Wrap usize>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ WRAPQUUX => {}, -LL + Wrap(_) => todo!() - | +LL | WRAPQUUX => {}, Wrap(_) => todo!() + | ++++++++++++++++++++ -error: aborting due to 10 previous errors; 1 warning emitted +error: aborting due to 10 previous errors; 9 warnings emitted For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr index ff29de03d6b3..24f3eaa5230d 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 5b81a8c3d3c0..8f9bd5bde89a 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 | _ => {}, | ^ @@ -10,26 +10,26 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: unreachable pattern - --> $DIR/empty-match.rs:61:9 - | -LL | _ if false => {}, - | ^ - -error: unreachable pattern - --> $DIR/empty-match.rs:68:9 - | -LL | _ => {}, - | ^ - error: unreachable pattern --> $DIR/empty-match.rs:71:9 | LL | _ if false => {}, | ^ +error: unreachable pattern + --> $DIR/empty-match.rs:78:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $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 6d17455086be..7f0389f40e23 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 | _ => {}, | ^ @@ -10,26 +10,26 @@ note: the lint level is defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: unreachable pattern - --> $DIR/empty-match.rs:61:9 - | -LL | _ if false => {}, - | ^ - -error: unreachable pattern - --> $DIR/empty-match.rs:68:9 - | -LL | _ => {}, - | ^ - error: unreachable pattern --> $DIR/empty-match.rs:71:9 | LL | _ if false => {}, | ^ +error: unreachable pattern + --> $DIR/empty-match.rs:78:9 + | +LL | _ => {}, + | ^ + +error: unreachable pattern + --> $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 d56d2e3c817c..fe5d0bce14fe 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 6d5e2f410bc9..9feedfde4697 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` 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` 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 b8b17918aef8..8dc534916061 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 4973e42b0544..40b42af26b34 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 b3e40b992399..50e13bdfdfed 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 5145f769075d..1d1ea8e49646 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 8489e2f14b87..a9e55fa53a68 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 98e417a17f86..310049fe13ec 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 e59e8885e1a4..4bebd3cbbefd 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 f914b98d9231..cceb1d8f65dd 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 f944c25a905c..f75517fb7910 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 22425aa0dd4d..3d2b540a9f57 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 }, - | ^ 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 d776249b2318..4a4945156f73 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 000000000000..4f6290808fc0 --- /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 000000000000..39adc0fde44e --- /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 730fd6d60264..9d0439d9d876 100644 --- a/tests/ui/resolve/issue-82865.stderr +++ b/tests/ui/resolve/issue-82865.stderr @@ -15,6 +15,13 @@ LL | Box::z LL | mac!(); | ------ in this macro invocation | +note: if you're trying to build a new `Box<_, _>` consider using one of the following associated functions: + Box::::new + Box::::new_uninit + Box::::new_zeroed + Box::::try_new + and 18 others + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/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 2b3fbd2a4d28..e591b2a93e12 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.rs @@ -40,7 +40,8 @@ fn main() { const CFN1: Wrap = Wrap(trivial); let input: Wrap = Wrap(trivial); match Wrap(input) { - Wrap(CFN1) => count += 1, + Wrap(CFN1) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -48,7 +49,8 @@ fn main() { const CFN2: Wrap = Wrap(sm_to); let input: Wrap = Wrap(sm_to); match Wrap(input) { - Wrap(CFN2) => count += 1, + Wrap(CFN2) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -56,7 +58,8 @@ fn main() { const CFN3: Wrap SM> = Wrap(to_sm); let input: Wrap SM> = Wrap(to_sm); match Wrap(input) { - Wrap(CFN3) => count += 1, + Wrap(CFN3) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -64,7 +67,8 @@ fn main() { const CFN4: Wrap = Wrap(not_sm_to); let input: Wrap = Wrap(not_sm_to); match Wrap(input) { - Wrap(CFN4) => count += 1, + Wrap(CFN4) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -72,7 +76,8 @@ fn main() { const CFN5: Wrap NotSM> = Wrap(to_not_sm); let input: Wrap NotSM> = Wrap(to_not_sm); match Wrap(input) { - Wrap(CFN5) => count += 1, + Wrap(CFN5) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -80,7 +85,8 @@ fn main() { const CFN6: Wrap = Wrap(r_sm_to); let input: Wrap = Wrap(r_sm_to); match Wrap(input) { - Wrap(CFN6) => count += 1, + Wrap(CFN6) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -88,7 +94,8 @@ fn main() { const CFN7: Wrap &SM> = Wrap(r_to_r_sm); let input: Wrap &SM> = Wrap(r_to_r_sm); match Wrap(input) { - Wrap(CFN7) => count += 1, + Wrap(CFN7) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -96,7 +103,8 @@ fn main() { const CFN8: Wrap = Wrap(r_not_sm_to); let input: Wrap = Wrap(r_not_sm_to); match Wrap(input) { - Wrap(CFN8) => count += 1, + Wrap(CFN8) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -104,7 +112,8 @@ fn main() { const CFN9: Wrap &NotSM> = Wrap(r_to_r_not_sm); let input: Wrap &NotSM> = Wrap(r_to_r_not_sm); match Wrap(input) { - Wrap(CFN9) => count += 1, + Wrap(CFN9) => count += 1, //~WARN behave unpredictably + //~| previously accepted Wrap(_) => {} }; @@ -126,7 +135,8 @@ fn main() { let input = Foo { alpha: not_sm_to, beta: to_not_sm, gamma: sm_to, delta: to_sm }; match input { - CFOO => count += 1, + CFOO => count += 1, //~WARN behave unpredictably + //~| previously accepted Foo { .. } => {} }; diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr new file mode 100644 index 000000000000..080bf5885ba7 --- /dev/null +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr @@ -0,0 +1,93 @@ +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:43:14 + | +LL | Wrap(CFN1) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + = note: `#[warn(pointer_structural_match)]` on by default + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:52:14 + | +LL | Wrap(CFN2) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14 + | +LL | Wrap(CFN3) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14 + | +LL | Wrap(CFN4) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14 + | +LL | Wrap(CFN5) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14 + | +LL | Wrap(CFN6) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14 + | +LL | Wrap(CFN7) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14 + | +LL | Wrap(CFN8) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14 + | +LL | Wrap(CFN9) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9 + | +LL | CFOO => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: 10 warnings emitted + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs index 567685950e9e..b05b8c8da1f3 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 d6afc0255ec4..4fdfce60bb86 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -1,5 +1,5 @@ -warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. - --> $DIR/issue-63479-match-fnptr.rs:35:7 +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:36:7 | LL | B(TEST) => println!("matched"), | ^^^^ @@ -12,5 +12,14 @@ note: the lint level is defined here LL | #![warn(pointer_structural_match)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 1 warning emitted +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:42:5 + | +LL | TEST2 => println!("matched"), + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #62411 + +warning: 2 warnings emitted diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr index de1bf8be8854..7386f10a6fb2 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 000000000000..9192c66143cc --- /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 000000000000..46093eb9fb35 --- /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 000000000000..33f9f56a5bbc --- /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 a9c54af0418a..c125756a646d 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 ec2a2f6f0553..7a12aca8520d 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 b6b777ec56c4..19e2546b0da8 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 6d436018bf4b..e6b663c47d75 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr @@ -1,3 +1,11 @@ +error: `~const` is not allowed here + --> $DIR/assoc-type-const-bound-usage.rs:7:17 + | +LL | type Assoc: ~const Foo; + | ^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + error[E0308]: mismatched types --> $DIR/assoc-type-const-bound-usage.rs:12:5 | @@ -7,6 +15,6 @@ LL | ::Assoc::foo(); = note: expected constant `host` found constant `true` -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr index 0cffae1da8d9..7df16ca5a3b4 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 similarity index 92% rename from tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs rename to tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs index 1e22ddcea8d3..0025449c4921 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl, effects)] +#![feature(const_trait_impl)] #[const_trait] trait MyTrait { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.stderr rename to tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.stderr 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 23e368870258..be75e852e0ac 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr @@ -1,19 +1,10 @@ -error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:19:32 +error: `~const` is not allowed here + --> $DIR/const-drop.rs:67:38 | -LL | const fn a(_: T) {} - | ^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions - -error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:24:13 +LL | pub struct ConstDropWithBound(pub core::marker::PhantomData); + | ^^^^^^^^^^^^^^^^ | -LL | let _ = S(&mut c); - | ^^^^^^^^^- value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions + = note: this item cannot have `~const` trait bounds -error: aborting due to 2 previous errors +error: aborting due to 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 0a9cf638a2d2..9da84cdb0525 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs @@ -63,6 +63,7 @@ mod t { fn foo() {} } + // FIXME(effects): This should be a `const` bound instead of a `~const` one. pub struct ConstDropWithBound(pub core::marker::PhantomData); impl const Drop for ConstDropWithBound { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr index 23e368870258..be75e852e0ac 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr @@ -1,19 +1,10 @@ -error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:19:32 +error: `~const` is not allowed here + --> $DIR/const-drop.rs:67:38 | -LL | const fn a(_: T) {} - | ^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions - -error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time - --> $DIR/const-drop.rs:24:13 +LL | pub struct ConstDropWithBound(pub core::marker::PhantomData); + | ^^^^^^^^^^^^^^^^ | -LL | let _ = S(&mut c); - | ^^^^^^^^^- value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions + = note: this item cannot have `~const` trait bounds -error: aborting due to 2 previous errors +error: aborting due to 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 000000000000..6598d1da0f86 --- /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 000000000000..002d586ac64f --- /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 000000000000..1954d2942e0b --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/ice-113375-index-out-of-bounds-generics.rs @@ -0,0 +1,18 @@ +// check-pass + +// effects ice https://github.com/rust-lang/rust/issues/113375 index out of bounds + +#![allow(incomplete_features, unused)] +#![feature(effects, adt_const_params)] + +struct Bar(T); + +impl Bar { + const fn value() -> usize { + 42 + } +} + +struct Foo::value()]>; + +pub fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs deleted file mode 100644 index 21ddf4ab4e5f..000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(const_trait_impl)] - -#[const_trait] -trait Bar {} - -fn foo() where T: ~const Bar {} -//~^ ERROR `~const` is not allowed - -fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr deleted file mode 100644 index b2a9365378b3..000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-90052.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: `~const` is not allowed here - --> $DIR/issue-90052.rs:6:22 - | -LL | fn foo() where T: ~const Bar {} - | ^^^^^^^^^^ - | -note: this function is not `const`, so it cannot have `~const` trait bounds - --> $DIR/issue-90052.rs:6:4 - | -LL | fn foo() where T: ~const Bar {} - | ^^^ - -error: aborting due to previous error - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/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 3db59631ef8d..234b0dd00638 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.rs @@ -18,11 +18,7 @@ trait Bar { fn bar(); } -// bgr360: I was only able to exercise the code path that raises the -// "missing ~const qualifier" error by making this base impl non-const, even -// though that doesn't really make sense to do. As seen below, if the base impl -// is made const, rustc fails earlier with an overlapping impl failure. -impl Bar for T +impl const Bar for T where T: ~const Foo, { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr index b60399c57dca..204f0f9f89ff 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 5d34156a5196..06330958b8e0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr @@ -1,11 +1,14 @@ -error[E0015]: cannot call non-const fn `::a` in constant functions - --> $DIR/super-traits-fail-2.rs:16:7 +error: `~const` is not allowed here + --> $DIR/super-traits-fail-2.rs:11:12 | -LL | x.a(); - | ^^^ +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^ | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-2.rs:11:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error -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 eb12a236d8c3..77b13a351e2b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -1,3 +1,15 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-3.rs:13:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-3.rs:13:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + error: ~const can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:13:19 | @@ -13,10 +25,10 @@ LL | trait Bar: ~const Foo {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:17:24 + --> $DIR/super-traits-fail-3.rs:18:24 | LL | const fn foo(x: &T) { | ^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs index 16c592830d78..5994057b2db2 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs @@ -13,6 +13,7 @@ trait Foo { trait Bar: ~const Foo {} //[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` //[ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]` +//[yn,nn]~^^^ ERROR: `~const` is not allowed here const fn foo(x: &T) { //[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr index 58225b945912..2e41eb9b4c45 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr @@ -1,8 +1,20 @@ +error: `~const` is not allowed here + --> $DIR/super-traits-fail-3.rs:13:12 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/super-traits-fail-3.rs:13:1 + | +LL | trait Bar: ~const Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:17:24 + --> $DIR/super-traits-fail-3.rs:18:24 | LL | const fn foo(x: &T) { | ^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yy.stderr index 6bc643e68710..d81d9aa94da3 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 `::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 95f7aaba0fc3..bbe1194f7a31 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs @@ -1,7 +1,55 @@ #![feature(const_trait_impl)] -#![feature(associated_type_bounds)] -struct TildeQuestion(std::marker::PhantomData); -//~^ ERROR `~const` and `?` are mutually exclusive +#[const_trait] +trait Trait {} + +// Regression test for issue #90052. +fn non_const_function() {} //~ ERROR `~const` is not allowed + +struct Struct { field: T } //~ ERROR `~const` is not allowed here +struct TupleStruct(T); //~ ERROR `~const` is not allowed here +struct UnitStruct; //~ ERROR `~const` is not allowed here + +enum Enum { Variant(T) } //~ ERROR `~const` is not allowed here + +union Union { field: T } //~ ERROR `~const` is not allowed here + +type Type = T; //~ ERROR `~const` is not allowed here + +const CONSTANT: () = (); //~ ERROR `~const` is not allowed here +//~^ ERROR generic const items are experimental + +trait NonConstTrait { + type Type: ~const Trait; + //~^ ERROR `~const` is not allowed + //~| ERROR `~const` is not allowed + fn non_const_function(); //~ ERROR `~const` is not allowed + const CONSTANT: (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +impl NonConstTrait for () { + type Type = (); //~ ERROR `~const` is not allowed + fn non_const_function() {} //~ ERROR `~const` is not allowed + const CONSTANT: () = (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +struct Implementor; + +impl Implementor { + type Type = (); //~ ERROR `~const` is not allowed + //~^ ERROR inherent associated types are unstable + fn non_const_function() {} //~ ERROR `~const` is not allowed + const CONSTANT: () = (); //~ ERROR `~const` is not allowed + //~^ ERROR generic const items are experimental +} + +// non-const traits +trait Child0: ~const Trait {} //~ ERROR `~const` is not allowed +trait Child1 where Self: ~const Trait {} //~ ERROR `~const` is not allowed + +// non-const impl +impl Trait for T {} //~ ERROR `~const` is not allowed fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr index d20f146df3f1..c14f9a990358 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -1,8 +1,244 @@ -error: `~const` and `?` are mutually exclusive - --> $DIR/tilde-const-invalid-places.rs:4:25 +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:7:26 | -LL | struct TildeQuestion(std::marker::PhantomData); - | ^^^^^^^^^^^^^ +LL | fn non_const_function() {} + | ^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:7:4 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:9:18 + | +LL | struct Struct { field: T } + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:10:23 + | +LL | struct TupleStruct(T); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:11:22 + | +LL | struct UnitStruct; + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:13:14 + | +LL | enum Enum { Variant(T) } + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:15:16 + | +LL | union Union { field: T } + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:17:14 + | +LL | type Type = T; + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:19:19 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:23:18 + | +LL | type Type: ~const Trait; + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:23:33 + | +LL | type Type: ~const Trait; + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:26:30 + | +LL | fn non_const_function(); + | ^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:26:8 + | +LL | fn non_const_function(); + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:27:23 + | +LL | const CONSTANT: (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:32:18 + | +LL | type Type = (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:33:30 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:33:8 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:34:23 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:41:18 + | +LL | type Type = (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:43:30 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:43:8 + | +LL | fn non_const_function() {} + | ^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:44:23 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:49:15 + | +LL | trait Child0: ~const Trait {} + | ^^^^^^^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:49:1 + | +LL | trait Child0: ~const Trait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:50:26 + | +LL | trait Child1 where Self: ~const Trait {} + | ^^^^^^^^^^^^ + | +note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:50:1 + | +LL | trait Child1 where Self: ~const Trait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places.rs:53:9 + | +LL | impl Trait for T {} + | ^^^^^^^^^^^^ + | +note: this impl is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places.rs:53:1 + | +LL | impl Trait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:19:15 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:27:19 + | +LL | const CONSTANT: (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:34:19 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: generic const items are experimental + --> $DIR/tilde-const-invalid-places.rs:44:19 + | +LL | const CONSTANT: () = (); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #113521 for more information + = help: add `#![feature(generic_const_items)]` to the crate attributes to enable + +error[E0658]: inherent associated types are unstable + --> $DIR/tilde-const-invalid-places.rs:41:5 + | +LL | type Type = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + +error: aborting due to 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 000000000000..ed911d965d63 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs @@ -0,0 +1,6 @@ +#![feature(const_trait_impl)] + +const fn tilde_question() {} +//~^ ERROR `~const` and `?` are mutually exclusive + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr new file mode 100644 index 000000000000..ce74ff8dde75 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr @@ -0,0 +1,8 @@ +error: `~const` and `?` are mutually exclusive + --> $DIR/tilde-const-maybe-trait.rs:3:28 + | +LL | const fn tilde_question() {} + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/span/issue-37767.stderr b/tests/ui/span/issue-37767.stderr index b612fdf16fc8..457870821a19 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 000000000000..43ebc5bac8cb --- /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 000000000000..ba635ab1fe67 --- /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 128160f10adb..2dd6fb6a3bf6 100644 --- a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr +++ b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr @@ -18,7 +18,10 @@ error[E0599]: no method named `sort` found for unit type `()` in the current sco --> $DIR/chain-method-call-mutation-in-place.rs:3:72 | LL | vec![1, 2, 3].into_iter().collect::>().sort_by_key(|i| i).sort(); - | ^^^^ method not found in `()` + | ------------- --------------------- ^^^^ method not found in `()` + | | | + | | method `sort` is available on `&mut [i32]` + | method `sort` is available on `Vec` | note: method `sort_by_key` modifies its receiver in-place, it is not meant to be used in method chains. --> $DIR/chain-method-call-mutation-in-place.rs:3:53 diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index 1cc37d61151c..0372a7e6cc0a 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::::new + Vec::::with_capacity + Vec::::from_raw_parts + Vec::::new_in + and 2 others + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: the function `contains` is implemented on `[_]` | LL | <[_]>::contains(&vec, &0); diff --git a/tests/ui/suggestions/import-trait-for-method-call.rs b/tests/ui/suggestions/import-trait-for-method-call.rs index 4dbadbdf9820..feb2c7e84f1d 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 4ef5948d9bf2..644841fdf7ed 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 000000000000..09b4f2bd47ca --- /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 000000000000..f09675fcc5c9 --- /dev/null +++ b/tests/ui/suggestions/issue-117669.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-117669.rs:2:20 + | +LL | let abs: i32 = 3i32.checked_abs(); + | --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found `Option` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Option` +help: consider using `Option::expect` to unwrap the `Option` value, panicking if the value is an `Option::None` + | +LL | let abs: i32 = 3i32.checked_abs().expect("REASON"); + | +++++++++++++++++ + +error: aborting due to 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 000000000000..84315ad91732 --- /dev/null +++ b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.fixed @@ -0,0 +1,11 @@ +// run-rustfix +use std::any::Any; + +fn foo(value: &T) -> Box { + Box::new(value) as Box + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let _ = foo(&5); +} diff --git a/tests/ui/issues/issue-16922.rs b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs similarity index 92% rename from tests/ui/issues/issue-16922.rs rename to tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs index bbbbf72dbd5d..fa7e72ff2a73 100644 --- a/tests/ui/issues/issue-16922.rs +++ b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs @@ -1,3 +1,4 @@ +// run-rustfix use std::any::Any; fn foo(value: &T) -> Box { diff --git a/tests/ui/issues/issue-16922.stderr b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.stderr similarity index 87% rename from tests/ui/issues/issue-16922.stderr rename to tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.stderr index 9d9f32a97c06..dc5817bfe0f5 100644 --- a/tests/ui/issues/issue-16922.stderr +++ b/tests/ui/suggestions/lifetimes/suggest-using-tick-underscore-lifetime-in-return-trait-object.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/issue-16922.rs:4:5 + --> $DIR/suggest-using-tick-underscore-lifetime-in-return-trait-object.rs:5:5 | LL | fn foo(value: &T) -> Box { | - let's call the lifetime of this reference `'1` diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr index adf01339972e..23f6657f092a 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 2f376065fdfb..f39dfd401e07 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 000000000000..bd0d72938f4d --- /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 000000000000..d34544c5c277 --- /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 similarity index 88% rename from tests/ui/thread-local/thread-local-static.stderr rename to tests/ui/thread-local/thread-local-static.mir.stderr index 712050a25fcf..607d7ee902cb 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 c7fee9e6b4c5..afaffbb7e9bb 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 000000000000..607d7ee902cb --- /dev/null +++ b/tests/ui/thread-local/thread-local-static.thir.stderr @@ -0,0 +1,44 @@ +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:10:12 + | +LL | const fn g(x: &mut [u32; 8]) { + | ^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0625]: thread-local statics cannot be accessed at compile-time + --> $DIR/thread-local-static.rs:12:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + +error[E0013]: constant functions cannot refer to statics + --> $DIR/thread-local-static.rs:12:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:12:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/thread-local-static.rs:12:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0013, E0133, E0625, E0658. +For more information about an error, try `rustc --explain E0013`. diff --git a/tests/ui/traits/new-solver/specialization-transmute.rs b/tests/ui/traits/new-solver/specialization-transmute.rs index f6b19e7adf51..fac7d76f8cf5 100644 --- a/tests/ui/traits/new-solver/specialization-transmute.rs +++ b/tests/ui/traits/new-solver/specialization-transmute.rs @@ -10,7 +10,7 @@ trait Default { } impl Default for T { - default type Id = T; + default type Id = T; //~ ERROR type annotations needed // This will be fixed by #111994 fn intu(&self) -> &Self::Id { //~ ERROR type annotations needed self diff --git a/tests/ui/traits/new-solver/specialization-transmute.stderr b/tests/ui/traits/new-solver/specialization-transmute.stderr index 09b1405fefbf..18965a465b3f 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 `::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 `::Id` -For more information about this error, try `rustc --explain E0284`. +error: aborting due to 2 previous errors; 1 warning emitted + +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 02150689ee5c..7fd753109be2 100644 --- a/tests/ui/traits/new-solver/specialization-unconstrained.rs +++ b/tests/ui/traits/new-solver/specialization-unconstrained.rs @@ -11,7 +11,7 @@ trait Default { } impl Default for T { - default type Id = T; + default type Id = T; //~ ERROR type annotations needed } fn test, U>() {} diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.stderr b/tests/ui/traits/new-solver/specialization-unconstrained.stderr index 910925cbaeb0..ed4dafa1484c 100644 --- a/tests/ui/traits/new-solver/specialization-unconstrained.stderr +++ b/tests/ui/traits/new-solver/specialization-unconstrained.stderr @@ -20,6 +20,13 @@ note: required by a bound in `test` LL | fn test, U>() {} | ^^^^^^ required by this bound in `test` -error: aborting due to previous error; 1 warning emitted +error[E0282]: type annotations needed + --> $DIR/specialization-unconstrained.rs:14:22 + | +LL | default type Id = T; + | ^ cannot infer type for associated type `::Id` -For more information about this error, try `rustc --explain E0284`. +error: aborting due to 2 previous errors; 1 warning emitted + +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 000000000000..9f373cc50f0a --- /dev/null +++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/non-lifetime-via-dyn-builtin.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr new file mode 100644 index 000000000000..9f373cc50f0a --- /dev/null +++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/non-lifetime-via-dyn-builtin.rs:5:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.rs b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs new file mode 100644 index 000000000000..9a8a5ced2e25 --- /dev/null +++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs @@ -0,0 +1,16 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next +// check-pass + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete and may not be safe + +fn trivial() +where + for dyn Fn(A, *const B): Fn(A, *const B), +{ +} + +fn main() { + trivial::(); +} diff --git a/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs b/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs new file mode 100644 index 000000000000..b999f251d333 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/disqualifying-object-candidates.rs @@ -0,0 +1,19 @@ +// check-pass + +trait Foo { + type Bar + where + dyn Send + 'static: Send; +} + +impl Foo for () { + type Bar = i32; + // We take `<() as Foo>::Bar: Sized` and normalize it under the where clause + // of `for <() as Foo>::Bar = i32`. This gives us back `i32: Send` with + // the nested obligation `(dyn Send + 'static): Send`. However, during candidate + // assembly for object types, we disqualify any obligations that has non-region + // late-bound vars in the param env(!), rather than just the predicate. This causes + // the where clause to not hold even though it trivially should. +} + +fn main() {} diff --git a/tests/ui/traits/object/print_vtable_sizes.stdout b/tests/ui/traits/object/print_vtable_sizes.stdout index ce90c76217b9..b43e168df3f3 100644 --- a/tests/ui/traits/object/print_vtable_sizes.stdout +++ b/tests/ui/traits/object/print_vtable_sizes.stdout @@ -1,11 +1,11 @@ -print-vtable-sizes { "crate_name": "", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" } -print-vtable-sizes { "crate_name": "", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" } -print-vtable-sizes { "crate_name": "", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" } -print-vtable-sizes { "crate_name": "", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "help::MarkerWithSuper", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "help::Super", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } -print-vtable-sizes { "crate_name": "", "trait_name": "help::V", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::MarkerWithSuper", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::Super", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } +print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::V", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } diff --git a/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs b/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs index f6cbbf04d826..6a2ee761e191 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 2063becdb083..80b6aaaf919f 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 `::recur` - --> $DIR/indirect-recursion-issue-112047.rs:22:5 + = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async block@$DIR/indirect-recursion-issue-112047.rs:22:9: 22:42}>`... + = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async block@$DIR/indirect-recursion-issue-112047.rs:22:9: 22:42}>`... + = note: ...which again requires computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:22:9: 22:42}`, completing the cycle +note: cycle used when elaborating drops for `::recur` + --> $DIR/indirect-recursion-issue-112047.rs:21:5 | LL | fn recur(self) -> Self::Recur { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/union/union-unsafe.mir.stderr b/tests/ui/union/union-unsafe.mir.stderr index 544213dbc554..15f059ffa487 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 5e1837a901d4..d1465486f778 100644 --- a/tests/ui/union/union-unsafe.rs +++ b/tests/ui/union/union-unsafe.rs @@ -1,30 +1,31 @@ // revisions: mir thir // [thir]compile-flags: -Z thir-unsafeck -use std::mem::ManuallyDrop; use std::cell::RefCell; +use std::mem::ManuallyDrop; union U1 { - a: u8 + a: u8, } union U2 { - a: ManuallyDrop + a: ManuallyDrop, } union U3 { - a: ManuallyDrop + a: ManuallyDrop, } union U4 { - a: T + a: T, } union URef { p: &'static mut i32, } -union URefCell { // field that does not drop but is not `Copy`, either +union URefCell { + // field that does not drop but is not `Copy`, either a: (ManuallyDrop>, i32), } @@ -62,6 +63,7 @@ fn main() { let U1 { a } = u1; //~ ERROR access to union field is unsafe if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe + if let Some(U1 { a: 13 }) = Some(u1) {} //~ ERROR access to union field is unsafe // let U1 { .. } = u1; // OK let mut u2 = U2 { a: ManuallyDrop::new(String::from("old")) }; // OK diff --git a/tests/ui/union/union-unsafe.thir.stderr b/tests/ui/union/union-unsafe.thir.stderr index f959fe5bdb5c..9ce835497c51 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 similarity index 80% rename from tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr rename to tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr index fbc621f4d0e3..ea53bf59d310 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 a192f3445f73..1b429955cb03 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 000000000000..d63843ed2b36 --- /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 427843f8d45c..dc6bd72f56c5 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 9a6bb18f9266..ad9d598aba2a 100644 --- a/tests/ui/unsafe/ranged_ints2.rs +++ b/tests/ui/unsafe/ranged_ints2.rs @@ -9,4 +9,5 @@ pub(crate) struct NonZero(pub(crate) T); fn main() { let mut x = unsafe { NonZero(1) }; let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe + if let Some(NonZero(ref mut y)) = Some(x) {} //~ ERROR mutation of layout constrained field is unsafe } diff --git a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr index 427843f8d45c..dc6bd72f56c5 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 4cdd97e5e06a..ad0621a1d043 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 similarity index 73% rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed rename to tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed index db1c102210e3..b59029df6429 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed @@ -1,7 +1,10 @@ // run-rustfix // aux-build:external_unsafe_macro.rs +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +#![crate_name = "wrapping_unsafe_block_sugg"] extern crate external_unsafe_macro; @@ -9,11 +12,13 @@ unsafe fn unsf() {} pub unsafe fn foo() { unsafe { //~^ NOTE an unsafe function restricts its caller, but its body is safe by default - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE }} @@ -39,10 +44,12 @@ pub unsafe fn baz() -> i32 { unsafe { }} macro_rules! unsafe_macro { () => (unsf()) } -//~^ ERROR call to unsafe function is unsafe +//[mir]~^ ERROR call to unsafe function is unsafe +//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE -//~| ERROR call to unsafe function is unsafe +//[mir]~| ERROR call to unsafe function is unsafe +//[thir]~| ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr similarity index 86% rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr rename to tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr index 43f619c27d27..7a1b83c7367d 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr @@ -1,21 +1,3 @@ -error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:12: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 - | -LL | pub unsafe fn foo() { - | ^^^^^^^^^^^^^^^^^^^ -note: the lint level is defined here - --> $DIR/wrapping-unsafe-block-sugg.rs:4: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 | @@ -23,22 +5,40 @@ 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 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: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 9c6be45896e2..3629b8a1beb5 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 000000000000..b59029df6429 --- /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 000000000000..b1fb35f85a60 --- /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 54afeaa7edab..782e7dc5e005 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `for fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ()): Foo` is not satisfied +error[E0277]: the trait bound `for fn(&ReBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ()): Foo` is not satisfied --> $DIR/higher-ranked-fn-type.rs:20:5 | LL | called() - | ^^^^^^ the trait `for Foo` is not implemented for `fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())` + | ^^^^^^ the trait `for Foo` is not implemented for `fn(&ReBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())` | help: this trait has no implementations, consider adding one --> $DIR/higher-ranked-fn-type.rs:6:1 diff --git a/triagebot.toml b/triagebot.toml index b419727bcfdd..4c8c1c59beba 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",